From f66739111f48bcaf7a8ad73fa2006250ebd2d261 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Thu, 24 Jul 2025 14:02:52 +0600 Subject: [PATCH 1/7] feat: Save SSO provider UserId in preference We need to access SSO provider's UID to make some SSO queries (ex: syncing 2FA state). We can retrieve this uid from accessToken's sub claim. We can save this uid on nextcloud's user preference. issue: https://gitlab.e.foundation/e/infra/backlog/-/issues/4352 --- lib/AppInfo/Application.php | 2 ++ lib/Controller/LoginController.php | 2 ++ lib/Provider/OpenIDConnectClient.php | 12 +++++++++++- lib/Service/TokenService.php | 16 ++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index bdf58c1..9f4f6ec 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -26,6 +26,8 @@ use OCP\Util; class Application extends App implements IBootstrap { + public const APP_ID = 'oidc_login'; + public const OIDC_PROVIDER_UID_KEY = 'oidc_uid'; private const TOKEN_LOGIN_KEY = 'is_oidc_token_login'; protected IURLGenerator $url; protected IL10N $l; diff --git a/lib/Controller/LoginController.php b/lib/Controller/LoginController.php index d02c3ab..a581a3c 100644 --- a/lib/Controller/LoginController.php +++ b/lib/Controller/LoginController.php @@ -146,6 +146,8 @@ class LoginController extends Controller $this->tokenService->updateTokens($user, $tokenResponse); } + $this->tokenService->persistOIDCProviderUID($user, $oidc); + // Workaround to create user files folder. Remove it later. \OC::$server->get(IRootFolder::class)->getUserFolder($user->getUID()); diff --git a/lib/Provider/OpenIDConnectClient.php b/lib/Provider/OpenIDConnectClient.php index ff33157..67f2749 100644 --- a/lib/Provider/OpenIDConnectClient.php +++ b/lib/Provider/OpenIDConnectClient.php @@ -217,6 +217,16 @@ class OpenIDConnectClient extends \Jumbojett\OpenIDConnectClient return $end_session_endpoint; } + public function getUserId(): ?string { + if ($this->isJWT($this->accessToken)) { + $claims = $this->decodeJWT($this->accessToken, 1); + } else { + $claims = $this->introspectToken($this->accessToken); + } + + return $claims->sub; + } + protected function getSessionKey($key) { return $this->session->get($key); @@ -331,4 +341,4 @@ class OpenIDConnectClient extends \Jumbojett\OpenIDConnectClient return $resp; } -} \ No newline at end of file +} diff --git a/lib/Service/TokenService.php b/lib/Service/TokenService.php index 0db5def..f89ff8d 100644 --- a/lib/Service/TokenService.php +++ b/lib/Service/TokenService.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace OCA\OIDCLogin\Service; +use OCA\OIDCLogin\AppInfo\Application; use OCA\OIDCLogin\Db\Entities\RefreshToken; use OCA\OIDCLogin\Db\Mappers\RefreshTokenMapper; use OCA\OIDCLogin\Events\AccessTokenUpdatedEvent; @@ -195,4 +196,19 @@ class TokenService $this->session->set('oidc_logout_url', false); } } + + public function persistOIDCProviderUID(IUser $user, OpenIDConnectClient $oidc) { + $userId = (string) $user->getUID(); + $savedOIDCUid = $this->config->getUserValue($userId, Application::APP_ID, Application::OIDC_PROVIDER_UID_KEY); + if ($savedOIDCUid !== null && trim($savedOIDCUid) !== '') { + return; + } + + $oidcUid = $oidc->getUserId(); + if ($oidcUid === null || trim($oidcUid) === '') { + return; + } + + $this->config->setUserValue($userId, Application::APP_ID, Application::OIDC_PROVIDER_UID_KEY, $oidcUid); + } } -- GitLab From 4bc26407cbaacf6dcedda619a1cd972fc26435a2 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Fri, 25 Jul 2025 15:16:21 +0600 Subject: [PATCH 2/7] chore: bump verion to 3.2.2-3 --- appinfo/info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appinfo/info.xml b/appinfo/info.xml index 5918f2c..44223cf 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -18,7 +18,7 @@ Provides user creation and login via one single OpenID Connect provider. Even th - Automatic redirection from the nextcloud login page to the Identity Provider login page - WebDAV endpoints `Bearer` and `Basic` authentication ]]> - 3.2.2-2 + 3.2.2-3 agpl pulsejet OIDCLogin -- GitLab From 08cba25d66546ca3073448633b8cf13fdfe92d5d Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Fri, 25 Jul 2025 18:08:29 +0600 Subject: [PATCH 3/7] chore: remove duplication app_id variable --- lib/AppInfo/Application.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 9f4f6ec..67be19a 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -39,11 +39,9 @@ class Application extends App implements IBootstrap /** @var LoginService */ private $loginService; - private $appName = 'oidc_login'; - public function __construct() { - parent::__construct($this->appName); + parent::__construct(self::APP_ID); } public function register(IRegistrationContext $context): void @@ -168,7 +166,7 @@ class Application extends App implements IBootstrap // Hide password change form if ($this->config->getSystemValue('oidc_login_hide_password_form', false)) { - Util::addStyle($this->appName, 'oidc.hidepasswordform'); + Util::addStyle(self::APP_ID, 'oidc.hidepasswordform'); } return; @@ -229,7 +227,7 @@ class Application extends App implements IBootstrap $bearerAuthBackend->login($bearerToken); $session->set(self::TOKEN_LOGIN_KEY, 1); } catch (\Exception $e) { - $logger->debug("OIDC Bearer token validation failed with: {$e->getMessage()}", ['app' => $this->appName]); + $logger->debug("OIDC Bearer token validation failed with: {$e->getMessage()}", ['app' => self::APP_ID]); } } } -- GitLab From 42e492c7aef7c18eeb013fd4b378a65221cb0337 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 29 Jul 2025 11:14:04 +0600 Subject: [PATCH 4/7] rnd: check UID varification code --- lib/Provider/OpenIDConnectClient.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/Provider/OpenIDConnectClient.php b/lib/Provider/OpenIDConnectClient.php index 67f2749..65c757a 100644 --- a/lib/Provider/OpenIDConnectClient.php +++ b/lib/Provider/OpenIDConnectClient.php @@ -217,14 +217,18 @@ class OpenIDConnectClient extends \Jumbojett\OpenIDConnectClient return $end_session_endpoint; } - public function getUserId(): ?string { + public function getUserId(): ?string { + $sub = $this->getVerifiedClaims('sub'); + \OC::$server->getLogger()->debug('fahim404: UID: '. $sub); if ($this->isJWT($this->accessToken)) { $claims = $this->decodeJWT($this->accessToken, 1); } else { $claims = $this->introspectToken($this->accessToken); } - return $claims->sub; + \OC::$server->getLogger()->debug('fahim404: UID from jwt: '. $claims->sub); + + return $claims->sub; } protected function getSessionKey($key) -- GitLab From 016f4cdc4783341850a1a05c443c8cd7bfc3026f Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 29 Jul 2025 11:26:56 +0600 Subject: [PATCH 5/7] feat: replace OIDC UID retrieval JWT code with pre-existing method --- lib/Provider/OpenIDConnectClient.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/lib/Provider/OpenIDConnectClient.php b/lib/Provider/OpenIDConnectClient.php index 65c757a..73fc2d5 100644 --- a/lib/Provider/OpenIDConnectClient.php +++ b/lib/Provider/OpenIDConnectClient.php @@ -218,17 +218,7 @@ class OpenIDConnectClient extends \Jumbojett\OpenIDConnectClient } public function getUserId(): ?string { - $sub = $this->getVerifiedClaims('sub'); - \OC::$server->getLogger()->debug('fahim404: UID: '. $sub); - if ($this->isJWT($this->accessToken)) { - $claims = $this->decodeJWT($this->accessToken, 1); - } else { - $claims = $this->introspectToken($this->accessToken); - } - - \OC::$server->getLogger()->debug('fahim404: UID from jwt: '. $claims->sub); - - return $claims->sub; + return $this->getVerifiedClaims('sub'); } protected function getSessionKey($key) -- GitLab From 7efdecbc19cb18b6f9fe8377d16f628b46506a8e Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 29 Jul 2025 11:30:15 +0600 Subject: [PATCH 6/7] chore: fix indentation & order of variable declaration --- lib/AppInfo/Application.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 67be19a..7fe2d49 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -26,13 +26,15 @@ use OCP\Util; class Application extends App implements IBootstrap { - public const APP_ID = 'oidc_login'; - public const OIDC_PROVIDER_UID_KEY = 'oidc_uid'; - private const TOKEN_LOGIN_KEY = 'is_oidc_token_login'; + public const APP_ID = 'oidc_login'; + public const OIDC_PROVIDER_UID_KEY = 'oidc_uid'; + protected IURLGenerator $url; protected IL10N $l; protected IConfig $config; + private const TOKEN_LOGIN_KEY = 'is_oidc_token_login'; + /** @var TokenService */ private $tokenService; -- GitLab From c11c40f26d4fe90ab7120b74d949b288ab40e6f1 Mon Sep 17 00:00:00 2001 From: Fahim Salam Chowdhury Date: Tue, 29 Jul 2025 11:34:27 +0600 Subject: [PATCH 7/7] chore: fix indentation --- lib/Controller/LoginController.php | 2 +- lib/Provider/OpenIDConnectClient.php | 2 +- lib/Service/TokenService.php | 26 +++++++++++++------------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/Controller/LoginController.php b/lib/Controller/LoginController.php index a581a3c..730b871 100644 --- a/lib/Controller/LoginController.php +++ b/lib/Controller/LoginController.php @@ -146,7 +146,7 @@ class LoginController extends Controller $this->tokenService->updateTokens($user, $tokenResponse); } - $this->tokenService->persistOIDCProviderUID($user, $oidc); + $this->tokenService->persistOIDCProviderUID($user, $oidc); // Workaround to create user files folder. Remove it later. \OC::$server->get(IRootFolder::class)->getUserFolder($user->getUID()); diff --git a/lib/Provider/OpenIDConnectClient.php b/lib/Provider/OpenIDConnectClient.php index 73fc2d5..06380d1 100644 --- a/lib/Provider/OpenIDConnectClient.php +++ b/lib/Provider/OpenIDConnectClient.php @@ -219,7 +219,7 @@ class OpenIDConnectClient extends \Jumbojett\OpenIDConnectClient public function getUserId(): ?string { return $this->getVerifiedClaims('sub'); - } + } protected function getSessionKey($key) { diff --git a/lib/Service/TokenService.php b/lib/Service/TokenService.php index f89ff8d..9f9f192 100644 --- a/lib/Service/TokenService.php +++ b/lib/Service/TokenService.php @@ -197,18 +197,18 @@ class TokenService } } - public function persistOIDCProviderUID(IUser $user, OpenIDConnectClient $oidc) { + public function persistOIDCProviderUID(IUser $user, OpenIDConnectClient $oidc) { $userId = (string) $user->getUID(); - $savedOIDCUid = $this->config->getUserValue($userId, Application::APP_ID, Application::OIDC_PROVIDER_UID_KEY); - if ($savedOIDCUid !== null && trim($savedOIDCUid) !== '') { - return; - } - - $oidcUid = $oidc->getUserId(); - if ($oidcUid === null || trim($oidcUid) === '') { - return; - } - - $this->config->setUserValue($userId, Application::APP_ID, Application::OIDC_PROVIDER_UID_KEY, $oidcUid); - } + $savedOIDCUid = $this->config->getUserValue($userId, Application::APP_ID, Application::OIDC_PROVIDER_UID_KEY); + if ($savedOIDCUid !== null && trim($savedOIDCUid) !== '') { + return; + } + + $oidcUid = $oidc->getUserId(); + if ($oidcUid === null || trim($oidcUid) === '') { + return; + } + + $this->config->setUserValue($userId, Application::APP_ID, Application::OIDC_PROVIDER_UID_KEY, $oidcUid); + } } -- GitLab