Skip to content

Commit b36bf39

Browse files
committed
Merge #17 Fix backchannel logout for Telekom and keep backward compatibility V31
2 parents b578fda + 65be061 commit b36bf39

File tree

1 file changed

+56
-15
lines changed

1 file changed

+56
-15
lines changed

lib/Controller/LoginController.php

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,26 @@ public function login(int $providerId, ?string $redirectUrl = null) {
161161
return $this->buildErrorTemplateResponse($message, Http::STATUS_NOT_FOUND, ['reason' => 'provider unreachable']);
162162
}
163163

164-
$state = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
165-
$this->session->set(self::STATE, $state);
166-
$this->session->set(self::REDIRECT_AFTER_LOGIN, $redirectUrl);
164+
// $state = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
165+
// $this->session->set(self::STATE, $state);
166+
// $this->session->set(self::REDIRECT_AFTER_LOGIN, $redirectUrl);
167167

168-
$nonce = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
169-
$this->session->set(self::NONCE, $nonce);
168+
// $nonce = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
169+
// $this->session->set(self::NONCE, $nonce);
170+
171+
// check if oidc state is present in session data
172+
if ($this->session->exists(self::STATE)) {
173+
$state = $this->session->get(self::STATE);
174+
$nonce = $this->session->get(self::NONCE);
175+
} else {
176+
$state = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
177+
$this->session->set(self::STATE, $state);
178+
$this->session->set(self::REDIRECT_AFTER_LOGIN, $redirectUrl);
179+
180+
$nonce = $this->random->generate(32, ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_UPPER);
181+
$this->session->set(self::NONCE, $nonce);
182+
$this->session->set(self::PROVIDERID, $providerId);
183+
}
170184

171185
$oidcSystemConfig = $this->config->getSystemValue('user_oidc', []);
172186
$isPkceSupported = in_array('S256', $discovery['code_challenge_methods_supported'] ?? [], true);
@@ -178,7 +192,7 @@ public function login(int $providerId, ?string $redirectUrl = null) {
178192
$this->session->set(self::CODE_VERIFIER, $code_verifier);
179193
}
180194

181-
$this->session->set(self::PROVIDERID, $providerId);
195+
// $this->session->set(self::PROVIDERID, $providerId);
182196
$this->session->close();
183197

184198
// get attribute mapping settings
@@ -507,6 +521,10 @@ public function code(string $state = '', string $code = '', string $scope = '',
507521
$this->userSession->createRememberMeToken($user);
508522
}
509523

524+
// remove code login session values
525+
$this->session->remove(self::STATE);
526+
$this->session->remove(self::NONCE);
527+
510528
// store all token information for potential token exchange requests
511529
$tokenData = array_merge(
512530
$data,
@@ -522,7 +540,8 @@ public function code(string $state = '', string $code = '', string $scope = '',
522540
try {
523541
$authToken = $this->authTokenProvider->getToken($this->session->getId());
524542
$this->sessionMapper->createSession(
525-
$idTokenPayload->sid ?? 'fallback-sid',
543+
//$idTokenPayload->sid ?? 'fallback-sid',
544+
$idTokenPayload->{'urn:telekom.com:session_token'} ?? 'fallback-sid',
526545
$idTokenPayload->sub ?? 'fallback-sub',
527546
$idTokenPayload->iss ?? 'fallback-iss',
528547
$authToken->getId(),
@@ -597,7 +616,9 @@ public function singleLogoutService() {
597616
}
598617

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

602623
$this->userSession->logout();
603624

@@ -685,7 +706,9 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
685706
}
686707

687708
$sub = $logoutTokenPayload->sub;
688-
if ($oidcSession->getSub() !== $sub) {
709+
// if ($oidcSession->getSub() !== $sub) {
710+
// handle sub only if it is available; session is enough to identify a logout
711+
if (isset($logoutTokenPayload->sub) && ($oidcSession->getSub() !== $sub)) {
689712
return $this->getBackchannelLogoutErrorResponse(
690713
'invalid SUB',
691714
'The sub does not match the one from the login ID token',
@@ -710,17 +733,19 @@ public function backChannelLogout(string $providerIdentifier, string $logout_tok
710733
$userId = $authToken->getUID();
711734
$this->authTokenProvider->invalidateTokenById($userId, $authToken->getId());
712735
} catch (InvalidTokenException $e) {
713-
return $this->getBackchannelLogoutErrorResponse(
714-
'nc session not found',
715-
'The authentication session was not found in Nextcloud',
716-
['nc_auth_session_not_found' => $authTokenId]
717-
);
736+
// it is not a problem if the auth token is already deleted, so no error
737+
// return $this->getBackchannelLogoutErrorResponse(
738+
// 'nc session not found',
739+
// 'The authentication session was not found in Nextcloud',
740+
// ['nc_auth_session_not_found' => $authTokenId]
741+
// );
718742
}
719743

720744
// cleanup
721745
$this->sessionMapper->delete($oidcSession);
722746

723-
return new JSONResponse([], Http::STATUS_OK);
747+
// return new JSONResponse([], Http::STATUS_OK);
748+
return new JSONResponse();
724749
}
725750

726751
/**
@@ -754,4 +779,20 @@ private function toCodeChallenge(string $data): string {
754779
$s = str_replace('/', '_', $s); // 63rd char of encoding
755780
return $s;
756781
}
782+
783+
/**
784+
* Backward compatible function for MagentaCLOUD to smoothly transition to new config
785+
*
786+
* @PublicPage
787+
* @NoCSRFRequired
788+
* @BruteForceProtection(action=userOidcBackchannelLogout)
789+
*
790+
* @param string $logout_token
791+
* @return JSONResponse
792+
* @throws Exception
793+
* @throws \JsonException
794+
*/
795+
public function telekomBackChannelLogout(string $logout_token = '') {
796+
return $this->backChannelLogout('Telekom', $logout_token);
797+
}
757798
}

0 commit comments

Comments
 (0)