@@ -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
@@ -621,6 +635,22 @@ public function code(string $state = '', string $code = '', string $scope = '',
621635 $ this ->eventDispatcher ->dispatchTyped (new UserLoggedInEvent ($ user , $ user ->getUID (), null , false ));
622636 }
623637
638+ // remove code login session values
639+ $ this ->session ->remove (self ::STATE );
640+ $ this ->session ->remove (self ::NONCE );
641+
642+ // $tokenExchangeEnabled = (isset($oidcSystemConfig['token_exchange']) && $oidcSystemConfig['token_exchange'] === true);
643+ // if ($tokenExchangeEnabled) {
644+ // store all token information for potential token exchange requests
645+ // $tokenData = array_merge(
646+ // $data,
647+ // ['provider_id' => $providerId],
648+ // );
649+ // $this->tokenService->storeToken($tokenData);
650+ // }
651+
652+ // $this->config->setUserValue($user->getUID(), Application::APP_ID, 'had_token_once', '1');
653+ /*
624654 $storeLoginTokenEnabled = $this->appConfig->getValueString(Application::APP_ID, 'store_login_token', '0') === '1';
625655 if ($storeLoginTokenEnabled) {
626656 // store all token information for potential token exchange requests
@@ -631,6 +661,7 @@ public function code(string $state = '', string $code = '', string $scope = '',
631661 $this->tokenService->storeToken($tokenData);
632662 }
633663 $this->config->setUserValue($user->getUID(), Application::APP_ID, 'had_token_once', '1');
664+ */
634665
635666 // Set last password confirm to the future as we don't have passwords to confirm against with SSO
636667 $ this ->session ->set ('last-password-confirm ' , strtotime ('+4 year ' , time ()));
@@ -639,7 +670,7 @@ public function code(string $state = '', string $code = '', string $scope = '',
639670 try {
640671 $ authToken = $ this ->authTokenProvider ->getToken ($ this ->session ->getId ());
641672 $ this ->sessionMapper ->createOrUpdateSession (
642- $ idTokenPayload ->sid ?? 'fallback-sid ' ,
673+ $ idTokenPayload ->{ ' urn:telekom.com:session_token ' } ?? 'fallback-sid ' ,
643674 $ idTokenPayload ->sub ?? 'fallback-sub ' ,
644675 $ idTokenPayload ->iss ?? 'fallback-iss ' ,
645676 $ authToken ->getId (),
@@ -743,7 +774,9 @@ public function singleLogoutService() {
743774 }
744775
745776 // cleanup related oidc session
746- $ this ->sessionMapper ->deleteFromNcSessionId ($ this ->session ->getId ());
777+ // it is not a good idea to remove the session early as some IDM send a backchannel logout also to the initiating system.
778+ // This will falsely fail if already deleted. So rely always on backchannel cleanup or make this an option?
779+ // $this->sessionMapper->deleteFromNcSessionId($this->session->getId());
747780
748781 $ this ->userSession ->logout ();
749782
@@ -812,7 +845,28 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
812845 );
813846 }
814847
815- if (!isset ($ logoutTokenPayload ->iss )) {
848+ // get the auth token ID associated with the logout token's sid attr
849+ $ sid = $ logoutTokenPayload ->sid ;
850+ try {
851+ $ oidcSession = $ this ->sessionMapper ->findSessionBySid ($ sid );
852+ } catch (DoesNotExistException $ e ) {
853+ return $ this ->getBackchannelLogoutErrorResponse (
854+ 'invalid SID ' ,
855+ 'The sid of the logout token was not found ' ,
856+ ['session_sid_not_found ' => $ sid ]
857+ );
858+ } catch (MultipleObjectsReturnedException $ e ) {
859+ return $ this ->getBackchannelLogoutErrorResponse (
860+ 'invalid SID ' ,
861+ 'The sid of the logout token was found multiple times ' ,
862+ ['multiple_logout_tokens_found ' => $ sid ]
863+ );
864+ }
865+
866+ $ sub = $ logoutTokenPayload ->sub ;
867+ // if ($oidcSession->getSub() !== $sub) {
868+ // handle sub only if it is available; session is enough to identify a logout
869+ if (isset ($ logoutTokenPayload ->sub ) && ($ oidcSession ->getSub () !== $ sub )) {
816870 return $ this ->getBackchannelLogoutErrorResponse (
817871 'invalid iss ' ,
818872 'The logout token should contain an iss attribute ' ,
@@ -894,7 +948,24 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
894948 $ this ->sessionMapper ->delete ($ oidcSession );
895949 }
896950
897- return new JSONResponse ([], Http::STATUS_OK );
951+ // return new JSONResponse([], Http::STATUS_OK);
952+ return new JSONResponse ();
953+ }
954+
955+ /**
956+ * Backward compatible function for MagentaCLOUD to smoothly transition to new config
957+ *
958+ * @PublicPage
959+ * @NoCSRFRequired
960+ * @BruteForceProtection(action=userOidcBackchannelLogout)
961+ *
962+ * @param string $logout_token
963+ * @return JSONResponse
964+ * @throws Exception
965+ * @throws \JsonException
966+ */
967+ public function telekomBackChannelLogout (string $ logout_token = '' ) {
968+ return $ this ->backChannelLogout ('Telekom ' , $ logout_token );
898969 }
899970
900971 /**
0 commit comments