@@ -94,6 +94,11 @@ public static function normalize(string $email): string
9494 */
9595 public function authenticate (string $ email ): string
9696 {
97+ $ authEndpoint = $ this ->fetchDiscovery ()->authorization_endpoint ?? null ;
98+ if (!is_string ($ authEndpoint )) {
99+ throw new \Exception ('No authorization_endpoint in discovery document ' );
100+ }
101+
97102 $ nonce = $ this ->store ->createNonce ($ email );
98103 $ query = http_build_query ([
99104 'login_hint ' => $ email ,
@@ -104,7 +109,7 @@ public function authenticate(string $email): string
104109 'client_id ' => $ this ->clientId ,
105110 'redirect_uri ' => $ this ->redirectUri ,
106111 ]);
107- return $ this -> broker . '/auth ? ' . $ query ;
112+ return $ authEndpoint . '? ' . $ query ;
108113 }
109114
110115 /**
@@ -126,13 +131,12 @@ public function verify(string $token): string
126131 }
127132
128133 // Fetch broker keys.
129- $ discoveryUrl = $ this ->broker . '/.well-known/openid-configuration ' ;
130- $ discoveryDoc = $ this ->store ->fetchCached ('discovery ' , $ discoveryUrl );
131- if (!isset ($ discoveryDoc ->jwks_uri ) || !is_string ($ discoveryDoc ->jwks_uri )) {
132- throw new \Exception ('Discovery document incorrectly formatted ' );
134+ $ jwksUri = $ this ->fetchDiscovery ()->jwks_uri ?? null ;
135+ if (!is_string ($ jwksUri )) {
136+ throw new \Exception ('No jwks_uri in discovery document ' );
133137 }
134138
135- $ keysDoc = $ this ->store ->fetchCached ('keys ' , $ discoveryDoc -> jwks_uri );
139+ $ keysDoc = $ this ->store ->fetchCached ('keys ' , $ jwksUri );
136140 if (!isset ($ keysDoc ->keys ) || !is_array ($ keysDoc ->keys )) {
137141 throw new \Exception ('Keys document incorrectly formatted ' );
138142 }
@@ -153,11 +157,13 @@ public function verify(string $token): string
153157 }
154158
155159 // Validate the token claims.
160+ $ clock = \Lcobucci \Clock \SystemClock::fromUTC ();
161+ $ leeway = new \DateInterval ('PT ' . $ this ->leeway . 'S ' );
156162 $ constraints = [
157163 new JwtConstraint \SignedWith (new JwtSigner \Rsa \Sha256 (), $ publicKey ),
158164 new JwtConstraint \IssuedBy ($ this ->broker ),
159165 new JwtConstraint \PermittedFor ($ this ->clientId ),
160- new JwtConstraint \LooseValidAt (\ Lcobucci \ Clock \SystemClock:: fromUTC () ),
166+ new JwtConstraint \LooseValidAt ($ clock , $ leeway ),
161167 ];
162168 $ jwt ->validator ()->assert ($ token , ...$ constraints );
163169
@@ -180,6 +186,15 @@ public function verify(string $token): string
180186 return $ email ;
181187 }
182188
189+ /**
190+ * Fetches the OpenID discovery document from the broker.
191+ */
192+ private function fetchDiscovery (): \stdClass
193+ {
194+ $ discoveryUrl = $ this ->broker . '/.well-known/openid-configuration ' ;
195+ return $ this ->store ->fetchCached ('discovery ' , $ discoveryUrl );
196+ }
197+
183198 /**
184199 * Parse a JWK into a PEM public key.
185200 */
0 commit comments