From a285ac15db2d9e4e54d8819d21a43e535d659480 Mon Sep 17 00:00:00 2001 From: s3n-w6i <37022952+s3n-w6i@users.noreply.github.com> Date: Fri, 8 May 2026 12:45:10 +0200 Subject: [PATCH 01/15] Add per-provider enrichLoginIdTokenWithUserinfo setting --- l10n/en_GB.js | 2 ++ lib/Controller/LoginController.php | 8 +++++++- lib/ResponseDefinitions.php | 1 + lib/Service/ProviderService.php | 3 +++ openapi.json | 6 +++++- src/components/AdminSettings.vue | 1 + src/components/SettingsForm.vue | 8 ++++++++ tests/unit/Service/ProviderServiceTest.php | 3 +++ 8 files changed, 30 insertions(+), 2 deletions(-) diff --git a/l10n/en_GB.js b/l10n/en_GB.js index 78d0d2ee8..51fd6baa5 100644 --- a/l10n/en_GB.js +++ b/l10n/en_GB.js @@ -114,6 +114,8 @@ OC.L10N.register( "Should the ID token be included as the id_token_hint GET parameter in the OpenID logout URL? Users are redirected to this URL after logging out of Nextcloud. Enabling this setting exposes the OIDC ID token to the user agent, which may not be necessary depending on the OIDC provider." : "Should the ID token be included as the id_token_hint GET parameter in the OpenID logout URL? Users are redirected to this URL after logging out of Nextcloud. Enabling this setting exposes the OIDC ID token to the user agent, which may not be necessary depending on the OIDC provider.", "Only groups matching the whitelist regex will be created, updated and deleted by the group claim. For example: {regex} allows all groups which ID starts with {substr}" : "Only groups matching the whitelist regex will be created, updated and deleted by the group claim. For example: {regex} allows all groups which ID starts with {substr}", "This will create and update the users groups depending on the groups claim in the ID token. The Format of the groups claim value should be {sample1}, {sample2} or {sample3}" : "This will create and update the users groups depending on the groups claim in the ID token. The Format of the groups claim value should be {sample1}, {sample2} or {sample3}", + "Enrich login ID token with userinfo": "Enrich login ID token with userinfo", + "Fetch additional information not found in the login ID token from the userinfo endpoint. This setting is overwritten if the global enrich_login_id_token_with_userinfo option is enabled.": "Fetch additional information not found in the login ID token from the userinfo endpoint. This setting is overwritten if the global enrich_login_id_token_with_userinfo option is enabled.", "Back to %s" : "Back to %s", "Domain" : "Domain", "your.domain" : "your.domain" diff --git a/lib/Controller/LoginController.php b/lib/Controller/LoginController.php index abba810cc..35b1970b3 100644 --- a/lib/Controller/LoginController.php +++ b/lib/Controller/LoginController.php @@ -539,7 +539,13 @@ public function code(string $state = '', string $code = '', string $scope = '', } // default is false - if (isset($oidcSystemConfig['enrich_login_id_token_with_userinfo']) && $oidcSystemConfig['enrich_login_id_token_with_userinfo']) { + $globalEnrichWithUserinfo = isset($oidcSystemConfig['enrich_login_id_token_with_userinfo']) && $oidcSystemConfig['enrich_login_id_token_with_userinfo']; + $providerEnrichWithUserinfo = $this->providerService->getSetting( + $provider->getId(), + ProviderService::SETTING_ENRICH_LOGIN_ID_TOKEN_WITH_USERINFO, + '0' + ) === '1'; + if ($globalEnrichWithUserinfo || $providerEnrichWithUserinfo) { $userInfo = $this->oidcService->userInfo($provider, $data['access_token']); $this->logger->debug('[UserInfoEnrich] Enriching the JWT payload with userinfo values'); foreach ($userInfo as $key => $value) { diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index b2c7153d9..bc55c4a21 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -46,6 +46,7 @@ * groupWhitelistRegex: string, * restrictLoginToGroups: bool, * nestedAndFallbackClaims: bool, + * enrichLoginIdTokenWithUserinfo: bool, * } * * @psalm-type UserOIDCProvider = array{ diff --git a/lib/Service/ProviderService.php b/lib/Service/ProviderService.php index f5a82a511..05a2a3646 100644 --- a/lib/Service/ProviderService.php +++ b/lib/Service/ProviderService.php @@ -61,6 +61,7 @@ class ProviderService { public const SETTING_RESTRICT_LOGIN_TO_GROUPS = 'restrictLoginToGroups'; public const SETTING_AZURE_GROUP_NAMES = 'azureGroupNames'; public const SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING = 'nestedAndFallbackClaims'; + public const SETTING_ENRICH_LOGIN_ID_TOKEN_WITH_USERINFO = 'enrichLoginIdTokenWithUserinfo'; public const BOOLEAN_SETTINGS_DEFAULT_VALUES = [ self::SETTING_GROUP_PROVISIONING => false, @@ -72,6 +73,7 @@ class ProviderService { self::SETTING_RESTRICT_LOGIN_TO_GROUPS => false, self::SETTING_AZURE_GROUP_NAMES => false, self::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING => false, + self::SETTING_ENRICH_LOGIN_ID_TOKEN_WITH_USERINFO => false, ]; public function __construct( @@ -195,6 +197,7 @@ public function getSupportedSettings(): array { self::SETTING_RESTRICT_LOGIN_TO_GROUPS, self::SETTING_AZURE_GROUP_NAMES, self::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING, + self::SETTING_ENRICH_LOGIN_ID_TOKEN_WITH_USERINFO, ]; } diff --git a/openapi.json b/openapi.json index 1b6450da2..ee522918e 100644 --- a/openapi.json +++ b/openapi.json @@ -124,7 +124,8 @@ "groupProvisioning", "groupWhitelistRegex", "restrictLoginToGroups", - "nestedAndFallbackClaims" + "nestedAndFallbackClaims", + "enrichLoginIdTokenWithUserinfo" ], "properties": { "mappingDisplayName": { @@ -231,6 +232,9 @@ }, "nestedAndFallbackClaims": { "type": "boolean" + }, + "enrichLoginIdTokenWithUserinfo": { + "type": "boolean" } } } diff --git a/src/components/AdminSettings.vue b/src/components/AdminSettings.vue index ea630bfbd..67e6ab399 100644 --- a/src/components/AdminSettings.vue +++ b/src/components/AdminSettings.vue @@ -203,6 +203,7 @@ export default { providerBasedId: false, groupProvisioning: false, sendIdTokenHint: true, + enrichLoginIdTokenWithUserinfo: false, }, }, showNewProvider: false, diff --git a/src/components/SettingsForm.vue b/src/components/SettingsForm.vue index 8abdab669..f0095b192 100644 --- a/src/components/SettingsForm.vue +++ b/src/components/SettingsForm.vue @@ -333,6 +333,14 @@

{{ t('user_oidc', 'Should the ID token be included as the id_token_hint GET parameter in the OpenID logout URL? Users are redirected to this URL after logging out of Nextcloud. Enabling this setting exposes the OIDC ID token to the user agent, which may not be necessary depending on the OIDC provider.') }}

+ + {{ t('user_oidc', 'Enrich login ID token with userinfo') }} + +

+ {{ t('user_oidc', 'Fetch additional information not found in the login ID token from the userinfo endpoint. This setting is overwritten if the global enrich_login_id_token_with_userinfo option is enabled.') }} +