@@ -165,12 +165,26 @@ public function login(int $providerId, ?string $redirectUrl = null) {
165165 return $ this ->buildErrorTemplateResponse ($ message , Http::STATUS_NOT_FOUND , ['reason ' => 'provider unreachable ' ]);
166166 }
167167
168- $ state = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
169- $ this ->session ->set (self ::STATE , $ state );
170- $ this ->session ->set (self ::REDIRECT_AFTER_LOGIN , $ redirectUrl );
168+ // $state = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
169+ // $this->session->set(self::STATE, $state);
170+ // $this->session->set(self::REDIRECT_AFTER_LOGIN, $redirectUrl);
171171
172- $ nonce = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
173- $ this ->session ->set (self ::NONCE , $ nonce );
172+ // $nonce = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
173+ // $this->session->set(self::NONCE, $nonce);
174+
175+ // check if oidc state is present in session data
176+ if ($ this ->session ->exists (self ::STATE )) {
177+ $ state = $ this ->session ->get (self ::STATE );
178+ $ nonce = $ this ->session ->get (self ::NONCE );
179+ } else {
180+ $ state = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
181+ $ this ->session ->set (self ::STATE , $ state );
182+ $ this ->session ->set (self ::REDIRECT_AFTER_LOGIN , $ redirectUrl );
183+
184+ $ nonce = $ this ->random ->generate (32 , ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER );
185+ $ this ->session ->set (self ::NONCE , $ nonce );
186+ $ this ->session ->set (self ::PROVIDERID , $ providerId );
187+ }
174188
175189 $ oidcSystemConfig = $ this ->config ->getSystemValue ('user_oidc ' , []);
176190 $ isPkceSupported = in_array ('S256 ' , $ discovery ['code_challenge_methods_supported ' ] ?? [], true );
@@ -182,7 +196,7 @@ public function login(int $providerId, ?string $redirectUrl = null) {
182196 $ this ->session ->set (self ::CODE_VERIFIER , $ code_verifier );
183197 }
184198
185- $ this ->session ->set (self ::PROVIDERID , $ providerId );
199+ // $this->session->set(self::PROVIDERID, $providerId);
186200 $ this ->session ->close ();
187201
188202 // get attribute mapping settings
@@ -518,16 +532,21 @@ public function code(string $state = '', string $code = '', string $scope = '',
518532 $ this ->eventDispatcher ->dispatchTyped (new UserLoggedInEvent ($ user , $ user ->getUID (), null , false ));
519533 }
520534
521- $ tokenExchangeEnabled = (isset ($ oidcSystemConfig ['token_exchange ' ]) && $ oidcSystemConfig ['token_exchange ' ] === true );
522- if ($ tokenExchangeEnabled ) {
535+ // remove code login session values
536+ $ this ->session ->remove (self ::STATE );
537+ $ this ->session ->remove (self ::NONCE );
538+
539+ // $tokenExchangeEnabled = (isset($oidcSystemConfig['token_exchange']) && $oidcSystemConfig['token_exchange'] === true);
540+ // if ($tokenExchangeEnabled) {
523541 // store all token information for potential token exchange requests
524- $ tokenData = array_merge (
525- $ data ,
526- ['provider_id ' => $ providerId ],
527- );
528- $ this ->tokenService ->storeToken ($ tokenData );
529- }
530- $ this ->config ->setUserValue ($ user ->getUID (), Application::APP_ID , 'had_token_once ' , '1 ' );
542+ // $tokenData = array_merge(
543+ // $data,
544+ // ['provider_id' => $providerId],
545+ // );
546+ // $this->tokenService->storeToken($tokenData);
547+ // }
548+
549+ // $this->config->setUserValue($user->getUID(), Application::APP_ID, 'had_token_once', '1');
531550
532551 // Set last password confirm to the future as we don't have passwords to confirm against with SSO
533552 $ this ->session ->set ('last-password-confirm ' , strtotime ('+4 year ' , time ()));
@@ -536,7 +555,8 @@ public function code(string $state = '', string $code = '', string $scope = '',
536555 try {
537556 $ authToken = $ this ->authTokenProvider ->getToken ($ this ->session ->getId ());
538557 $ this ->sessionMapper ->createSession (
539- $ idTokenPayload ->sid ?? 'fallback-sid ' ,
558+ //$idTokenPayload->sid ?? 'fallback-sid',
559+ $ idTokenPayload ->{'urn:telekom.com:session_token ' } ?? 'fallback-sid ' ,
540560 $ idTokenPayload ->sub ?? 'fallback-sub ' ,
541561 $ idTokenPayload ->iss ?? 'fallback-iss ' ,
542562 $ authToken ->getId (),
@@ -628,7 +648,9 @@ public function singleLogoutService() {
628648 }
629649
630650 // cleanup related oidc session
631- $ this ->sessionMapper ->deleteFromNcSessionId ($ this ->session ->getId ());
651+ // it is not a good idea to remove the session early as some IDM send a backchannel logout also to the initiating system.
652+ // This will falsely fail if already deleted. So rely always on backchannel cleanup or make this an option?
653+ // $this->sessionMapper->deleteFromNcSessionId($this->session->getId());
632654
633655 $ this ->userSession ->logout ();
634656
@@ -716,7 +738,9 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
716738 }
717739
718740 $ sub = $ logoutTokenPayload ->sub ;
719- if ($ oidcSession ->getSub () !== $ sub ) {
741+ // if ($oidcSession->getSub() !== $sub) {
742+ // handle sub only if it is available; session is enough to identify a logout
743+ if (isset ($ logoutTokenPayload ->sub ) && ($ oidcSession ->getSub () !== $ sub )) {
720744 return $ this ->getBackchannelLogoutErrorResponse (
721745 'invalid SUB ' ,
722746 'The sub does not match the one from the login ID token ' ,
@@ -741,17 +765,19 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
741765 $ userId = $ authToken ->getUID ();
742766 $ this ->authTokenProvider ->invalidateTokenById ($ userId , $ authToken ->getId ());
743767 } catch (InvalidTokenException $ e ) {
744- return $ this ->getBackchannelLogoutErrorResponse (
745- 'nc session not found ' ,
746- 'The authentication session was not found in Nextcloud ' ,
747- ['nc_auth_session_not_found ' => $ authTokenId ]
748- );
768+ // it is not a problem if the auth token is already deleted, so no error
769+ // return $this->getBackchannelLogoutErrorResponse(
770+ // 'nc session not found',
771+ // 'The authentication session was not found in Nextcloud',
772+ // ['nc_auth_session_not_found' => $authTokenId]
773+ // );
749774 }
750775
751776 // cleanup
752777 $ this ->sessionMapper ->delete ($ oidcSession );
753778
754- return new JSONResponse ([], Http::STATUS_OK );
779+ // return new JSONResponse([], Http::STATUS_OK);
780+ return new JSONResponse ();
755781 }
756782
757783 /**
@@ -785,4 +811,20 @@ private function toCodeChallenge(string $data): string {
785811 $ s = str_replace ('/ ' , '_ ' , $ s ); // 63rd char of encoding
786812 return $ s ;
787813 }
814+
815+ /**
816+ * Backward compatible function for MagentaCLOUD to smoothly transition to new config
817+ *
818+ * @PublicPage
819+ * @NoCSRFRequired
820+ * @BruteForceProtection(action=userOidcBackchannelLogout)
821+ *
822+ * @param string $logout_token
823+ * @return JSONResponse
824+ * @throws Exception
825+ * @throws \JsonException
826+ */
827+ public function telekomBackChannelLogout (string $ logout_token = '' ) {
828+ return $ this ->backChannelLogout ('Telekom ' , $ logout_token );
829+ }
788830}
0 commit comments