@@ -111,21 +111,22 @@ public function logout(): RedirectResponse
111111
112112 try {
113113 $ providerConfig = $ this ->providerConfigFactory ->create ();
114- if (!$ providerConfig ->enabled || $ providerConfig ->discoveryUrl === '' ) {
115- return new RedirectResponse ($ this ->configuration ->getDefaultUrl ());
116- }
117-
118114 $ idToken = $ this ->resolveLogoutIdToken ($ user );
119115
120116 $ user ->deleteFromSession ();
121117 $ this ->oidcSession ->clearIdToken ();
122118
119+ if (!$ providerConfig ->enabled || $ providerConfig ->discoveryUrl === '' ) {
120+ return new RedirectResponse ($ this ->configuration ->getDefaultUrl ());
121+ }
122+
123123 $ discoveryDocument = $ this ->discoveryService ->discover ($ providerConfig );
124124 $ logoutUrl = $ this ->oidcClient ->buildLogoutUrl ($ providerConfig , $ discoveryDocument , $ idToken );
125125
126126 return new RedirectResponse ($ logoutUrl ?? $ this ->configuration ->getDefaultUrl ());
127127 } catch (Exception ) {
128128 $ user ->deleteFromSession ();
129+ $ this ->oidcSession ->clearIdToken ();
129130 return new RedirectResponse ($ this ->configuration ->getDefaultUrl ());
130131 }
131132 }
@@ -171,26 +172,39 @@ public function callback(Request $request): Response
171172 $ code ,
172173 $ authorizationState ['verifier ' ],
173174 );
174- $ this ->idTokenValidator ->validate (
175+ $ idTokenClaims = $ this ->idTokenValidator ->validate (
175176 (string ) ($ token ['id_token ' ] ?? '' ),
176177 $ discoveryDocument ,
177178 $ providerConfig ->client ->clientId ,
178179 $ authorizationState ['nonce ' ],
179180 );
180181 $ claims = $ this ->oidcClient ->fetchUserInfo ($ discoveryDocument , (string ) $ token ['access_token ' ]);
182+
183+ $ idTokenSub = (string ) ($ idTokenClaims ['sub ' ] ?? '' );
184+ $ userInfoSub = (string ) ($ claims ['sub ' ] ?? '' );
185+ if ($ idTokenSub === '' || $ userInfoSub === '' || !hash_equals ($ idTokenSub , $ userInfoSub )) {
186+ $ this ->configuration
187+ ->getLogger ()
188+ ->warning ('Keycloak subject mismatch between ID token and UserInfo; aborting login. ' );
189+ $ this ->oidcSession ->clearAuthorizationState ();
190+ return $ redirect ;
191+ }
192+
181193 $ login = $ this ->resolveLocalLogin ($ claims );
182194 $ auth = new AuthKeycloak ($ this ->configuration , $ providerConfig , $ claims , $ login , $ this ->userFactory );
183195
184196 if (!$ auth ->isValidLogin ($ login )) {
185- $ this ->configuration ->getLogger ()->warning (sprintf ('Keycloak login not valid for user: %s ' , $ login ));
197+ $ this ->configuration
198+ ->getLogger ()
199+ ->warning (sprintf ('Keycloak login not valid for user: %s ' , $ this ->maskLogin ($ login )));
186200 $ this ->oidcSession ->clearAuthorizationState ();
187201 return $ redirect ;
188202 }
189203
190204 if (!$ auth ->checkCredentials ($ login , '' )) {
191205 $ this ->configuration
192206 ->getLogger ()
193- ->warning (sprintf ('Keycloak credentials not valid for user: %s ' , $ login ));
207+ ->warning (sprintf ('Keycloak credentials not valid for user: %s ' , $ this -> maskLogin ( $ login) ));
194208 $ this ->oidcSession ->clearAuthorizationState ();
195209 return $ redirect ;
196210 }
@@ -199,13 +213,15 @@ public function callback(Request $request): Response
199213 if (!$ user ->getUserByLogin ($ login )) {
200214 $ this ->configuration
201215 ->getLogger ()
202- ->warning (sprintf ('Keycloak user lookup failed for login: %s ' , $ login ));
216+ ->warning (sprintf ('Keycloak user lookup failed for login: %s ' , $ this -> maskLogin ( $ login) ));
203217 $ this ->oidcSession ->clearAuthorizationState ();
204218 return $ redirect ;
205219 }
206220
207221 if (!$ this ->synchronizeKeycloakSubject ($ user , $ claims )) {
208- $ this ->configuration ->getLogger ()->warning (sprintf ('Keycloak subject mismatch for user: %s ' , $ login ));
222+ $ this ->configuration
223+ ->getLogger ()
224+ ->warning (sprintf ('Keycloak subject mismatch for user: %s ' , $ this ->maskLogin ($ login )));
209225 $ this ->oidcSession ->clearAuthorizationState ();
210226 return $ redirect ;
211227 }
@@ -276,6 +292,16 @@ private function resolveLocalLogin(array $claims): string
276292 return $ subject ;
277293 }
278294
295+ private function maskLogin (string $ login ): string
296+ {
297+ $ login = trim ($ login );
298+ if ($ login === '' ) {
299+ return '<empty> ' ;
300+ }
301+
302+ return 'sha256: ' . substr (hash ('sha256 ' , $ login ), 0 , 12 );
303+ }
304+
279305 /** @param array<string, mixed> $claims */
280306 private function synchronizeKeycloakSubject (CurrentUser $ user , array $ claims ): bool
281307 {
0 commit comments