Skip to content

Commit 88122f4

Browse files
committed
Merge #17 Fix backchannel logout for Telekom and keep backward compatibility V31
2 parents 0be7877 + 65be061 commit 88122f4

1 file changed

Lines changed: 56 additions & 15 deletions

File tree

lib/Controller/LoginController.php

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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
@@ -528,6 +542,10 @@ public function code(string $state = '', string $code = '', string $scope = '',
528542
$this->userSession->createRememberMeToken($user);
529543
}
530544

545+
// remove code login session values
546+
$this->session->remove(self::STATE);
547+
$this->session->remove(self::NONCE);
548+
531549
// store all token information for potential token exchange requests
532550
$tokenData = array_merge(
533551
$data,
@@ -543,7 +561,8 @@ public function code(string $state = '', string $code = '', string $scope = '',
543561
try {
544562
$authToken = $this->authTokenProvider->getToken($this->session->getId());
545563
$this->sessionMapper->createSession(
546-
$idTokenPayload->sid ?? 'fallback-sid',
564+
//$idTokenPayload->sid ?? 'fallback-sid',
565+
$idTokenPayload->{'urn:telekom.com:session_token'} ?? 'fallback-sid',
547566
$idTokenPayload->sub ?? 'fallback-sub',
548567
$idTokenPayload->iss ?? 'fallback-iss',
549568
$authToken->getId(),
@@ -618,7 +637,9 @@ public function singleLogoutService() {
618637
}
619638

620639
// cleanup related oidc session
621-
$this->sessionMapper->deleteFromNcSessionId($this->session->getId());
640+
// it is not a good idea to remove the session early as some IDM send a backchannel logout also to the initiating system.
641+
// This will falsely fail if already deleted. So rely always on backchannel cleanup or make this an option?
642+
// $this->sessionMapper->deleteFromNcSessionId($this->session->getId());
622643

623644
$this->userSession->logout();
624645

@@ -706,7 +727,9 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
706727
}
707728

708729
$sub = $logoutTokenPayload->sub;
709-
if ($oidcSession->getSub() !== $sub) {
730+
// if ($oidcSession->getSub() !== $sub) {
731+
// handle sub only if it is available; session is enough to identify a logout
732+
if (isset($logoutTokenPayload->sub) && ($oidcSession->getSub() !== $sub)) {
710733
return $this->getBackchannelLogoutErrorResponse(
711734
'invalid SUB',
712735
'The sub does not match the one from the login ID token',
@@ -731,17 +754,19 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
731754
$userId = $authToken->getUID();
732755
$this->authTokenProvider->invalidateTokenById($userId, $authToken->getId());
733756
} catch (InvalidTokenException $e) {
734-
return $this->getBackchannelLogoutErrorResponse(
735-
'nc session not found',
736-
'The authentication session was not found in Nextcloud',
737-
['nc_auth_session_not_found' => $authTokenId]
738-
);
757+
// it is not a problem if the auth token is already deleted, so no error
758+
// return $this->getBackchannelLogoutErrorResponse(
759+
// 'nc session not found',
760+
// 'The authentication session was not found in Nextcloud',
761+
// ['nc_auth_session_not_found' => $authTokenId]
762+
// );
739763
}
740764

741765
// cleanup
742766
$this->sessionMapper->delete($oidcSession);
743767

744-
return new JSONResponse([], Http::STATUS_OK);
768+
// return new JSONResponse([], Http::STATUS_OK);
769+
return new JSONResponse();
745770
}
746771

747772
/**
@@ -775,4 +800,20 @@ private function toCodeChallenge(string $data): string {
775800
$s = str_replace('/', '_', $s); // 63rd char of encoding
776801
return $s;
777802
}
803+
804+
/**
805+
* Backward compatible function for MagentaCLOUD to smoothly transition to new config
806+
*
807+
* @PublicPage
808+
* @NoCSRFRequired
809+
* @BruteForceProtection(action=userOidcBackchannelLogout)
810+
*
811+
* @param string $logout_token
812+
* @return JSONResponse
813+
* @throws Exception
814+
* @throws \JsonException
815+
*/
816+
public function telekomBackChannelLogout(string $logout_token = '') {
817+
return $this->backChannelLogout('Telekom', $logout_token);
818+
}
778819
}

0 commit comments

Comments
 (0)