@@ -163,12 +163,26 @@ public function login(int $providerId, ?string $redirectUrl = null) {
163163 return $ this ->buildErrorTemplateResponse ($ message , Http::STATUS_NOT_FOUND , ['reason ' => 'provider unreachable ' ]);
164164 }
165165
166- $ state = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
167- $ this ->session ->set (self ::STATE , $ state );
168- $ this ->session ->set (self ::REDIRECT_AFTER_LOGIN , $ redirectUrl );
166+ // $state = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
167+ // $this->session->set(self::STATE, $state);
168+ // $this->session->set(self::REDIRECT_AFTER_LOGIN, $redirectUrl);
169169
170- $ nonce = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
171- $ this ->session ->set (self ::NONCE , $ nonce );
170+ // $nonce = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
171+ // $this->session->set(self::NONCE, $nonce);
172+
173+ // check if oidc state is present in session data
174+ if ($ this ->session ->exists (self ::STATE )) {
175+ $ state = $ this ->session ->get (self ::STATE );
176+ $ nonce = $ this ->session ->get (self ::NONCE );
177+ } else {
178+ $ state = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
179+ $ this ->session ->set (self ::STATE , $ state );
180+ $ this ->session ->set (self ::REDIRECT_AFTER_LOGIN , $ redirectUrl );
181+
182+ $ nonce = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
183+ $ this ->session ->set (self ::NONCE , $ nonce );
184+ $ this ->session ->set (self ::PROVIDERID , $ providerId );
185+ }
172186
173187 $ oidcSystemConfig = $ this ->config ->getSystemValue ('user_oidc ' , []);
174188 $ isPkceSupported = in_array ('S256 ' , $ discovery ['code_challenge_methods_supported ' ] ?? [], true );
@@ -180,7 +194,7 @@ public function login(int $providerId, ?string $redirectUrl = null) {
180194 $ this ->session ->set (self ::CODE_VERIFIER , $ code_verifier );
181195 }
182196
183- $ this ->session ->set (self ::PROVIDERID , $ providerId );
197+ // $this->session->set(self::PROVIDERID, $providerId);
184198 $ this ->session ->close ();
185199
186200 // get attribute mapping settings
@@ -517,14 +531,19 @@ public function code(string $state = '', string $code = '', string $scope = '',
517531 $ this ->userSession ->createRememberMeToken ($ user );
518532 }
519533
534+ // remove code login session values
535+ $ this ->session ->remove (self ::STATE );
536+ $ this ->session ->remove (self ::NONCE );
537+
520538 // Set last password confirm to the future as we don't have passwords to confirm against with SSO
521539 $ this ->session ->set ('last-password-confirm ' , strtotime ('+4 year ' , time ()));
522540
523541 // for backchannel logout
524542 try {
525543 $ authToken = $ this ->authTokenProvider ->getToken ($ this ->session ->getId ());
526544 $ this ->sessionMapper ->createSession (
527- $ idTokenPayload ->sid ?? 'fallback-sid ' ,
545+ //$idTokenPayload->sid ?? 'fallback-sid',
546+ $ idTokenPayload ->{'urn:telekom.com:session_token ' } ?? 'fallback-sid ' ,
528547 $ idTokenPayload ->sub ?? 'fallback-sub ' ,
529548 $ idTokenPayload ->iss ?? 'fallback-iss ' ,
530549 $ authToken ->getId (),
@@ -599,7 +618,9 @@ public function singleLogoutService() {
599618 }
600619
601620 // cleanup related oidc session
602- $ this ->sessionMapper ->deleteFromNcSessionId ($ this ->session ->getId ());
621+ // it is not a good idea to remove the session early as some IDM send a backchannel logout also to the initiating system.
622+ // This will falsely fail if already deleted. So rely always on backchannel cleanup or make this an option?
623+ // $this->sessionMapper->deleteFromNcSessionId($this->session->getId());
603624
604625 $ this ->userSession ->logout ();
605626
@@ -687,7 +708,9 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
687708 }
688709
689710 $ sub = $ logoutTokenPayload ->sub ;
690- if ($ oidcSession ->getSub () !== $ sub ) {
711+ // if ($oidcSession->getSub() !== $sub) {
712+ // handle sub only if it is available; session is enough to identify a logout
713+ if (isset ($ logoutTokenPayload ->sub ) && ($ oidcSession ->getSub () !== $ sub )) {
691714 return $ this ->getBackchannelLogoutErrorResponse (
692715 'invalid SUB ' ,
693716 'The sub does not match the one from the login ID token ' ,
@@ -712,17 +735,19 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
712735 $ userId = $ authToken ->getUID ();
713736 $ this ->authTokenProvider ->invalidateTokenById ($ userId , $ authToken ->getId ());
714737 } catch (InvalidTokenException $ e ) {
715- return $ this ->getBackchannelLogoutErrorResponse (
716- 'nc session not found ' ,
717- 'The authentication session was not found in Nextcloud ' ,
718- ['nc_auth_session_not_found ' => $ authTokenId ]
719- );
738+ // it is not a problem if the auth token is already deleted, so no error
739+ // return $this->getBackchannelLogoutErrorResponse(
740+ // 'nc session not found',
741+ // 'The authentication session was not found in Nextcloud',
742+ // ['nc_auth_session_not_found' => $authTokenId]
743+ // );
720744 }
721745
722746 // cleanup
723747 $ this ->sessionMapper ->delete ($ oidcSession );
724748
725- return new JSONResponse ([], Http::STATUS_OK );
749+ // return new JSONResponse([], Http::STATUS_OK);
750+ return new JSONResponse ();
726751 }
727752
728753 /**
@@ -756,4 +781,20 @@ private function toCodeChallenge(string $data): string {
756781 $ s = str_replace ('/ ' , '_ ' , $ s ); // 63rd char of encoding
757782 return $ s ;
758783 }
784+
785+ /**
786+ * Backward compatible function for MagentaCLOUD to smoothly transition to new config
787+ *
788+ * @PublicPage
789+ * @NoCSRFRequired
790+ * @BruteForceProtection(action=userOidcBackchannelLogout)
791+ *
792+ * @param string $logout_token
793+ * @return JSONResponse
794+ * @throws Exception
795+ * @throws \JsonException
796+ */
797+ public function telekomBackChannelLogout (string $ logout_token = '' ) {
798+ return $ this ->backChannelLogout ('Telekom ' , $ logout_token );
799+ }
759800}
0 commit comments