From 7d74e1323540cb4e66173c58286ed9f952d0461c Mon Sep 17 00:00:00 2001 From: "Bernd.Rederlechner@t-systems.com" Date: Wed, 27 Sep 2023 12:17:35 +0200 Subject: [PATCH 1/3] Fix the backchannel logout flow for Telekom --- lib/Controller/LoginController.php | 38 +++++++++++++++++------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/lib/Controller/LoginController.php b/lib/Controller/LoginController.php index b2db72ff..5901ee1c 100644 --- a/lib/Controller/LoginController.php +++ b/lib/Controller/LoginController.php @@ -509,7 +509,7 @@ public function code(string $state = '', string $code = '', string $scope = '', try { $authToken = $this->authTokenProvider->getToken($this->session->getId()); $this->sessionMapper->createSession( - $idTokenPayload->sid ?? 'fallback-sid', + $idTokenPayload->{'urn:telekom.com:session_token'} ?? 'fallback-sid', $idTokenPayload->sub ?? 'fallback-sub', $idTokenPayload->iss ?? 'fallback-iss', $authToken->getId(), @@ -577,8 +577,11 @@ public function singleLogoutService() { } } - // cleanup related oidc session - $this->sessionMapper->deleteFromNcSessionId($this->session->getId()); + // it is not a good idea to remove the session early as some IDM send + // a backchannel logout also to the initiating system. This will falsely fail + // if already deleted. So rely always on backchannel cleanup + // or make this an option? + //$this->sessionMapper->deleteFromNcSessionId($this->session->getId()); $this->userSession->logout(); @@ -666,14 +669,14 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok ); } - $sub = $logoutTokenPayload->sub; - if ($oidcSession->getSub() !== $sub) { - return $this->getBackchannelLogoutErrorResponse( - 'invalid SUB', - 'The sub does not match the one from the login ID token', - ['invalid_sub' => $sub] - ); - } + // handle sub only if it is available; session is enough to identify a logout, though + if (isset($logoutTokenPayload->sub) && ($oidcSession->getSub() !== $logoutTokenPayload->sub)) { + return $this->getBackchannelLogoutErrorResponse( + 'invalid SUB', + 'The sub does not match the one from the login ID token', + ['invalid_sub' => $sub] + ); + } $iss = $logoutTokenPayload->iss; if ($oidcSession->getIss() !== $iss) { return $this->getBackchannelLogoutErrorResponse( @@ -692,17 +695,18 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok $userId = $authToken->getUID(); $this->authTokenProvider->invalidateTokenById($userId, $authToken->getId()); } catch (InvalidTokenException $e) { - return $this->getBackchannelLogoutErrorResponse( - 'nc session not found', - 'The authentication session was not found in Nextcloud', - ['nc_auth_session_not_found' => $authTokenId] - ); + //it is not a problem if the auth token is already deleted, so no error + //return $this->getBackchannelLogoutErrorResponse( + // 'nc session not found', + // 'The authentication session was not found in Nextcloud', + // ['nc_auth_session_not_found' => $authTokenId] + //); } // cleanup $this->sessionMapper->delete($oidcSession); - return new JSONResponse([], Http::STATUS_OK); + return new JSONResponse(); } /** From 5ed47724feb065bd3143eb85690a4938cd6f2321 Mon Sep 17 00:00:00 2001 From: "Bernd.Rederlechner@t-systems.com" Date: Wed, 27 Sep 2023 12:39:27 +0200 Subject: [PATCH 2/3] Clean code --- lib/Controller/LoginController.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/Controller/LoginController.php b/lib/Controller/LoginController.php index 5901ee1c..53272706 100644 --- a/lib/Controller/LoginController.php +++ b/lib/Controller/LoginController.php @@ -669,14 +669,14 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok ); } - // handle sub only if it is available; session is enough to identify a logout, though - if (isset($logoutTokenPayload->sub) && ($oidcSession->getSub() !== $logoutTokenPayload->sub)) { - return $this->getBackchannelLogoutErrorResponse( - 'invalid SUB', - 'The sub does not match the one from the login ID token', - ['invalid_sub' => $sub] - ); - } + // handle sub only if it is available; session is enough to identify a logout, though + if (isset($logoutTokenPayload->sub) && ($oidcSession->getSub() !== $logoutTokenPayload->sub)) { + return $this->getBackchannelLogoutErrorResponse( + 'invalid SUB', + 'The sub does not match the one from the login ID token', + ['invalid_sub' => $sub] + ); + } $iss = $logoutTokenPayload->iss; if ($oidcSession->getIss() !== $iss) { return $this->getBackchannelLogoutErrorResponse( @@ -696,7 +696,7 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok $this->authTokenProvider->invalidateTokenById($userId, $authToken->getId()); } catch (InvalidTokenException $e) { //it is not a problem if the auth token is already deleted, so no error - //return $this->getBackchannelLogoutErrorResponse( + //return $this->getBackchannelLogoutErrorResponse( // 'nc session not found', // 'The authentication session was not found in Nextcloud', // ['nc_auth_session_not_found' => $authTokenId] From b2016b9cbf765e9ec7789366aedf62ac469875ed Mon Sep 17 00:00:00 2001 From: "Bernd.Rederlechner@t-systems.com" Date: Wed, 27 Sep 2023 13:00:18 +0200 Subject: [PATCH 3/3] Add backward compatible endpoint for silent switchover --- lib/Controller/LoginController.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/Controller/LoginController.php b/lib/Controller/LoginController.php index 53272706..b314076e 100644 --- a/lib/Controller/LoginController.php +++ b/lib/Controller/LoginController.php @@ -734,4 +734,20 @@ private function getBackchannelLogoutErrorResponse(string $error, string $descri } return $response; } + + /** + * Backward compatible function for MagentaCLOUD to smoothly transition to new config + * + * @PublicPage + * @NoCSRFRequired + * @BruteForceProtection(action=userOidcBackchannelLogout) + * + * @param string $logout_token + * @return JSONResponse + * @throws Exception + * @throws \JsonException + */ + public function telekomBackChannelLogout(string $logout_token = '') { + return $this->backChannelLogout('Telekom', $logout_token); + } }