@@ -172,12 +172,26 @@ public function login(int $providerId, ?string $redirectUrl = null) {
172172 return $ this ->buildErrorTemplateResponse ($ message , Http::STATUS_NOT_FOUND , ['reason ' => 'provider unreachable ' ]);
173173 }
174174
175- $ state = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
176- $ this ->session ->set (self ::STATE , $ state );
177- $ this ->session ->set (self ::REDIRECT_AFTER_LOGIN , $ redirectUrl );
175+ // $state = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
176+ // $this->session->set(self::STATE, $state);
177+ // $this->session->set(self::REDIRECT_AFTER_LOGIN, $redirectUrl);
178178
179- $ nonce = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
180- $ this ->session ->set (self ::NONCE , $ nonce );
179+ // $nonce = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
180+ // $this->session->set(self::NONCE, $nonce);
181+
182+ // check if oidc state is present in session data
183+ if ($ this ->session ->exists (self ::STATE )) {
184+ $ state = $ this ->session ->get (self ::STATE );
185+ $ nonce = $ this ->session ->get (self ::NONCE );
186+ } else {
187+ $ state = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
188+ $ this ->session ->set (self ::STATE , $ state );
189+ $ this ->session ->set (self ::REDIRECT_AFTER_LOGIN , $ redirectUrl );
190+
191+ $ nonce = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
192+ $ this ->session ->set (self ::NONCE , $ nonce );
193+ $ this ->session ->set (self ::PROVIDERID , $ providerId );
194+ }
181195
182196 $ oidcSystemConfig = $ this ->config ->getSystemValue ('user_oidc ' , []);
183197 $ isPkceSupported = in_array ('S256 ' , $ discovery ['code_challenge_methods_supported ' ] ?? [], true );
@@ -189,7 +203,7 @@ public function login(int $providerId, ?string $redirectUrl = null) {
189203 $ this ->session ->set (self ::CODE_VERIFIER , $ code_verifier );
190204 }
191205
192- $ this ->session ->set (self ::PROVIDERID , $ providerId );
206+ // $this->session->set(self::PROVIDERID, $providerId);
193207 $ this ->session ->close ();
194208
195209 // get attribute mapping settings
@@ -625,6 +639,22 @@ public function code(string $state = '', string $code = '', string $scope = '',
625639 $ this ->eventDispatcher ->dispatchTyped (new UserLoggedInEvent ($ user , $ user ->getUID (), null , false ));
626640 }
627641
642+ // remove code login session values
643+ $ this ->session ->remove (self ::STATE );
644+ $ this ->session ->remove (self ::NONCE );
645+
646+ // $tokenExchangeEnabled = (isset($oidcSystemConfig['token_exchange']) && $oidcSystemConfig['token_exchange'] === true);
647+ // if ($tokenExchangeEnabled) {
648+ // store all token information for potential token exchange requests
649+ // $tokenData = array_merge(
650+ // $data,
651+ // ['provider_id' => $providerId],
652+ // );
653+ // $this->tokenService->storeToken($tokenData);
654+ // }
655+
656+ // $this->config->setUserValue($user->getUID(), Application::APP_ID, 'had_token_once', '1');
657+ /*
628658 $storeLoginTokenEnabled = $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0') === '1';
629659 if ($storeLoginTokenEnabled) {
630660 // store all token information for potential token exchange requests
@@ -635,6 +665,7 @@ public function code(string $state = '', string $code = '', string $scope = '',
635665 $this->tokenService->storeToken($tokenData);
636666 }
637667 $this->config->setUserValue($user->getUID(), Application::APP_ID, 'had_token_once', '1');
668+ */
638669
639670 // Set last password confirm to the future as we don't have passwords to confirm against with SSO
640671 $ this ->session ->set ('last-password-confirm ' , strtotime ('+4 year ' , time ()));
@@ -643,7 +674,7 @@ public function code(string $state = '', string $code = '', string $scope = '',
643674 try {
644675 $ authToken = $ this ->authTokenProvider ->getToken ($ this ->session ->getId ());
645676 $ this ->sessionMapper ->createOrUpdateSession (
646- $ idTokenPayload ->sid ?? 'fallback-sid ' ,
677+ $ idTokenPayload ->{ ' urn:telekom.com:session_token ' } ?? 'fallback-sid ' ,
647678 $ idTokenPayload ->sub ?? 'fallback-sub ' ,
648679 $ idTokenPayload ->iss ?? 'fallback-iss ' ,
649680 $ authToken ->getId (),
@@ -747,7 +778,9 @@ public function singleLogoutService() {
747778 }
748779
749780 // cleanup related oidc session
750- $ this ->sessionMapper ->deleteFromNcSessionId ($ this ->session ->getId ());
781+ // it is not a good idea to remove the session early as some IDM send a backchannel logout also to the initiating system.
782+ // This will falsely fail if already deleted. So rely always on backchannel cleanup or make this an option?
783+ // $this->sessionMapper->deleteFromNcSessionId($this->session->getId());
751784
752785 $ this ->userSession ->logout ();
753786
@@ -816,7 +849,28 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
816849 );
817850 }
818851
819- if (!isset ($ logoutTokenPayload ->iss )) {
852+ // get the auth token ID associated with the logout token's sid attr
853+ $ sid = $ logoutTokenPayload ->sid ;
854+ try {
855+ $ oidcSession = $ this ->sessionMapper ->findSessionBySid ($ sid );
856+ } catch (DoesNotExistException $ e ) {
857+ return $ this ->getBackchannelLogoutErrorResponse (
858+ 'invalid SID ' ,
859+ 'The sid of the logout token was not found ' ,
860+ ['session_sid_not_found ' => $ sid ]
861+ );
862+ } catch (MultipleObjectsReturnedException $ e ) {
863+ return $ this ->getBackchannelLogoutErrorResponse (
864+ 'invalid SID ' ,
865+ 'The sid of the logout token was found multiple times ' ,
866+ ['multiple_logout_tokens_found ' => $ sid ]
867+ );
868+ }
869+
870+ $ sub = $ logoutTokenPayload ->sub ;
871+ // if ($oidcSession->getSub() !== $sub) {
872+ // handle sub only if it is available; session is enough to identify a logout
873+ if (isset ($ logoutTokenPayload ->sub ) && ($ oidcSession ->getSub () !== $ sub )) {
820874 return $ this ->getBackchannelLogoutErrorResponse (
821875 'invalid iss ' ,
822876 'The logout token should contain an iss attribute ' ,
@@ -898,7 +952,24 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
898952 $ this ->sessionMapper ->delete ($ oidcSession );
899953 }
900954
901- return new JSONResponse ([], Http::STATUS_OK );
955+ // return new JSONResponse([], Http::STATUS_OK);
956+ return new JSONResponse ();
957+ }
958+
959+ /**
960+ * Backward compatible function for MagentaCLOUD to smoothly transition to new config
961+ *
962+ * @PublicPage
963+ * @NoCSRFRequired
964+ * @BruteForceProtection(action=userOidcBackchannelLogout)
965+ *
966+ * @param string $logout_token
967+ * @return JSONResponse
968+ * @throws Exception
969+ * @throws \JsonException
970+ */
971+ public function telekomBackChannelLogout (string $ logout_token = '' ) {
972+ return $ this ->backChannelLogout ('Telekom ' , $ logout_token );
902973 }
903974
904975 /**
0 commit comments