@@ -162,12 +162,26 @@ public function login(int $providerId, ?string $redirectUrl = null) {
162162 return $ this ->buildErrorTemplateResponse ($ message , Http::STATUS_NOT_FOUND , ['reason ' => 'provider unreachable ' ]);
163163 }
164164
165- $ state = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
166- $ this ->session ->set (self ::STATE , $ state );
167- $ this ->session ->set (self ::REDIRECT_AFTER_LOGIN , $ redirectUrl );
165+ // $state = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
166+ // $this->session->set(self::STATE, $state);
167+ // $this->session->set(self::REDIRECT_AFTER_LOGIN, $redirectUrl);
168168
169- $ nonce = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
170- $ this ->session ->set (self ::NONCE , $ nonce );
169+ // $nonce = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
170+ // $this->session->set(self::NONCE, $nonce);
171+
172+ // check if oidc state is present in session data
173+ if ($ this ->session ->exists (self ::STATE )) {
174+ $ state = $ this ->session ->get (self ::STATE );
175+ $ nonce = $ this ->session ->get (self ::NONCE );
176+ } else {
177+ $ state = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
178+ $ this ->session ->set (self ::STATE , $ state );
179+ $ this ->session ->set (self ::REDIRECT_AFTER_LOGIN , $ redirectUrl );
180+
181+ $ nonce = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
182+ $ this ->session ->set (self ::NONCE , $ nonce );
183+ $ this ->session ->set (self ::PROVIDERID , $ providerId );
184+ }
171185
172186 $ oidcSystemConfig = $ this ->config ->getSystemValue ('user_oidc ' , []);
173187 $ isPkceSupported = in_array ('S256 ' , $ discovery ['code_challenge_methods_supported ' ] ?? [], true );
@@ -179,7 +193,7 @@ public function login(int $providerId, ?string $redirectUrl = null) {
179193 $ this ->session ->set (self ::CODE_VERIFIER , $ code_verifier );
180194 }
181195
182- $ this ->session ->set (self ::PROVIDERID , $ providerId );
196+ // $this->session->set(self::PROVIDERID, $providerId);
183197 $ this ->session ->close ();
184198
185199 // get attribute mapping settings
@@ -496,14 +510,19 @@ public function code(string $state = '', string $code = '', string $scope = '',
496510 $ this ->userSession ->createRememberMeToken ($ user );
497511 }
498512
513+ // remove code login session values
514+ $ this ->session ->remove (self ::STATE );
515+ $ this ->session ->remove (self ::NONCE );
516+
499517 // Set last password confirm to the future as we don't have passwords to confirm against with SSO
500518 $ this ->session ->set ('last-password-confirm ' , strtotime ('+4 year ' , time ()));
501519
502520 // for backchannel logout
503521 try {
504522 $ authToken = $ this ->authTokenProvider ->getToken ($ this ->session ->getId ());
505523 $ this ->sessionMapper ->createSession (
506- $ idTokenPayload ->sid ?? 'fallback-sid ' ,
524+ //$idTokenPayload->sid ?? 'fallback-sid',
525+ $ idTokenPayload ->{'urn:telekom.com:session_token ' } ?? 'fallback-sid ' ,
507526 $ idTokenPayload ->sub ?? 'fallback-sub ' ,
508527 $ idTokenPayload ->iss ?? 'fallback-iss ' ,
509528 $ authToken ->getId (),
@@ -578,7 +597,9 @@ public function singleLogoutService() {
578597 }
579598
580599 // cleanup related oidc session
581- $ this ->sessionMapper ->deleteFromNcSessionId ($ this ->session ->getId ());
600+ // it is not a good idea to remove the session early as some IDM send a backchannel logout also to the initiating system.
601+ // This will falsely fail if already deleted. So rely always on backchannel cleanup or make this an option?
602+ // $this->sessionMapper->deleteFromNcSessionId($this->session->getId());
582603
583604 $ this ->userSession ->logout ();
584605
@@ -666,7 +687,9 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
666687 }
667688
668689 $ sub = $ logoutTokenPayload ->sub ;
669- if ($ oidcSession ->getSub () !== $ sub ) {
690+ // if ($oidcSession->getSub() !== $sub) {
691+ // handle sub only if it is available; session is enough to identify a logout
692+ if (isset ($ logoutTokenPayload ->sub ) && ($ oidcSession ->getSub () !== $ sub )) {
670693 return $ this ->getBackchannelLogoutErrorResponse (
671694 'invalid SUB ' ,
672695 'The sub does not match the one from the login ID token ' ,
@@ -691,17 +714,19 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
691714 $ userId = $ authToken ->getUID ();
692715 $ this ->authTokenProvider ->invalidateTokenById ($ userId , $ authToken ->getId ());
693716 } catch (InvalidTokenException $ e ) {
694- return $ this ->getBackchannelLogoutErrorResponse (
695- 'nc session not found ' ,
696- 'The authentication session was not found in Nextcloud ' ,
697- ['nc_auth_session_not_found ' => $ authTokenId ]
698- );
717+ // it is not a problem if the auth token is already deleted, so no error
718+ // return $this->getBackchannelLogoutErrorResponse(
719+ // 'nc session not found',
720+ // 'The authentication session was not found in Nextcloud',
721+ // ['nc_auth_session_not_found' => $authTokenId]
722+ // );
699723 }
700724
701725 // cleanup
702726 $ this ->sessionMapper ->delete ($ oidcSession );
703727
704- return new JSONResponse ([], Http::STATUS_OK );
728+ // return new JSONResponse([], Http::STATUS_OK);
729+ return new JSONResponse ();
705730 }
706731
707732 /**
@@ -735,4 +760,20 @@ private function toCodeChallenge(string $data): string {
735760 $ s = str_replace ('/ ' , '_ ' , $ s ); // 63rd char of encoding
736761 return $ s ;
737762 }
763+
764+ /**
765+ * Backward compatible function for MagentaCLOUD to smoothly transition to new config
766+ *
767+ * @PublicPage
768+ * @NoCSRFRequired
769+ * @BruteForceProtection(action=userOidcBackchannelLogout)
770+ *
771+ * @param string $logout_token
772+ * @return JSONResponse
773+ * @throws Exception
774+ * @throws \JsonException
775+ */
776+ public function telekomBackChannelLogout (string $ logout_token = '' ) {
777+ return $ this ->backChannelLogout ('Telekom ' , $ logout_token );
778+ }
738779}
0 commit comments