diff --git a/README.md b/README.md
index 9bf7c263..811b20ed 100644
--- a/README.md
+++ b/README.md
@@ -331,6 +331,40 @@ This app can stop matching users (when a user search is performed in Nextcloud)
],
```
+### Optional: Enable support for nested and fallback claim mappings
+
+By default, claim mapping in this app uses **flat attribute keys** like `email`, `name`, `custom.nickname`, etc.
+However, some Identity Providers return **structured tokens** (nested JSON), and mapping such claims requires dot-notation (e.g. `custom.nickname` → `{ "custom": { "nickname": "value" } }`).
+
+Additionally, you may want to define **fallbacks**, in case a preferred claim is missing, using the `|` separator.
+
+#### Example
+
+```
+custom.nickname | profile.name | name
+```
+
+This will return the first non-empty string from the token in the order defined.
+
+
+#### Enabling this behavior (optional)
+
+To enable support for dot-notation and fallback claims for a specific provider, set the following configuration flag via the Nextcloud command line:
+
+```bash
+php occ user_oidc:provider --resolve-nested-claims=1
+```
+
+To disable again:
+
+```bash
+php occ user_oidc:provider --resolve-nested-claims=0
+```
+
+This setting is also available in the web interface when configuring a provider.
+This setting is **disabled by default** to ensure full backward compatibility with existing configurations and flat token structures.
+
+
## Building the app
Requirements for building:
diff --git a/lib/Command/UpsertProvider.php b/lib/Command/UpsertProvider.php
index d2fc286b..0182e070 100644
--- a/lib/Command/UpsertProvider.php
+++ b/lib/Command/UpsertProvider.php
@@ -143,6 +143,12 @@ class UpsertProvider extends Base {
'shortcut' => null, 'mode' => InputOption::VALUE_REQUIRED, 'setting_key' => ProviderService::SETTING_MAPPING_GROUPS,
'description' => 'Attribute mapping of the groups',
],
+ 'resolve-nested-claims' => [
+ 'shortcut' => null,
+ 'mode' => InputOption::VALUE_REQUIRED,
+ 'setting_key' => ProviderService::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING,
+ 'description' => 'Enable support for dot-separated and fallback claim mappings (e.g. "a.b | c.d | e"). 1 to enable, 0 to disable (default)',
+ ],
];
public function __construct(
diff --git a/lib/Controller/LoginController.php b/lib/Controller/LoginController.php
index 6c428c83..7ba5e612 100644
--- a/lib/Controller/LoginController.php
+++ b/lib/Controller/LoginController.php
@@ -199,6 +199,7 @@ public function login(int $providerId, ?string $redirectUrl = null) {
'userinfo' => [],
];
+ $resolveNestedClaims = $this->providerService->getSetting($providerId, ProviderService::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING, '0') === '1';
// by default: default claims are ENABLED
// default claims are historically for quota, email, displayName and groups
$isDefaultClaimsEnabled = !isset($oidcSystemConfig['enable_default_claims']) || $oidcSystemConfig['enable_default_claims'] !== false;
@@ -218,7 +219,20 @@ public function login(int $providerId, ?string $redirectUrl = null) {
$displaynameAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_DISPLAYNAME);
$quotaAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_QUOTA);
$groupsAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_GROUPS);
- foreach ([$emailAttribute, $displaynameAttribute, $quotaAttribute, $groupsAttribute] as $claim) {
+ $rawClaims = [$emailAttribute, $displaynameAttribute, $quotaAttribute, $groupsAttribute];
+
+ if ($resolveNestedClaims) {
+ $claimSet = [];
+ foreach ($rawClaims as $claim) {
+ if ($claim !== '') {
+ $first = trim(explode('|', $claim)[0]);
+ $claimSet[$first] = true;
+ }
+ }
+ $rawClaims = array_keys($claimSet);
+ }
+
+ foreach ($rawClaims as $claim) {
if ($claim !== '') {
$claims['id_token'][$claim] = null;
$claims['userinfo'][$claim] = null;
@@ -227,8 +241,12 @@ public function login(int $providerId, ?string $redirectUrl = null) {
}
if ($uidAttribute !== 'sub') {
- $claims['id_token'][$uidAttribute] = ['essential' => true];
- $claims['userinfo'][$uidAttribute] = ['essential' => true];
+ $uidAttributeToRequest = $uidAttribute;
+ if ($resolveNestedClaims) {
+ $uidAttributeToRequest = trim(explode('|', $uidAttribute)[0]);
+ }
+ $claims['id_token'][$uidAttributeToRequest] = ['essential' => true];
+ $claims['userinfo'][$uidAttributeToRequest] = ['essential' => true];
}
$extraClaimsString = $this->providerService->getSetting($providerId, ProviderService::SETTING_EXTRA_CLAIMS, '');
@@ -459,7 +477,8 @@ public function code(string $state = '', string $code = '', string $scope = '',
// get user ID attribute
$uidAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_UID, 'sub');
- $userId = $idTokenPayload->{$uidAttribute} ?? null;
+ $userId = $this->provisioningService->getClaimValue($idTokenPayload, $uidAttribute, $providerId);
+
if ($userId === null) {
$message = $this->l10n->t('Failed to provision the user');
return $this->build403TemplateResponse($message, Http::STATUS_BAD_REQUEST, ['reason' => 'failed to provision user']);
diff --git a/lib/Service/ProviderService.php b/lib/Service/ProviderService.php
index ae2d41b2..6ecac6ff 100644
--- a/lib/Service/ProviderService.php
+++ b/lib/Service/ProviderService.php
@@ -51,6 +51,7 @@ class ProviderService {
public const SETTING_GROUP_PROVISIONING = 'groupProvisioning';
public const SETTING_GROUP_WHITELIST_REGEX = 'groupWhitelistRegex';
public const SETTING_RESTRICT_LOGIN_TO_GROUPS = 'restrictLoginToGroups';
+ public const SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING = 'nestedAndFallbackClaims';
public const BOOLEAN_SETTINGS_DEFAULT_VALUES = [
self::SETTING_GROUP_PROVISIONING => false,
@@ -60,6 +61,7 @@ class ProviderService {
self::SETTING_CHECK_BEARER => false,
self::SETTING_SEND_ID_TOKEN_HINT => false,
self::SETTING_RESTRICT_LOGIN_TO_GROUPS => false,
+ self::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING => false,
];
public function __construct(
@@ -168,6 +170,7 @@ private function getSupportedSettings(): array {
self::SETTING_GROUP_PROVISIONING,
self::SETTING_GROUP_WHITELIST_REGEX,
self::SETTING_RESTRICT_LOGIN_TO_GROUPS,
+ self::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING,
];
}
diff --git a/lib/Service/ProvisioningService.php b/lib/Service/ProvisioningService.php
index a853d95d..8dddd616 100644
--- a/lib/Service/ProvisioningService.php
+++ b/lib/Service/ProvisioningService.php
@@ -58,6 +58,52 @@ public function hasOidcUserProvisitioned(string $userId): bool {
return false;
}
+ /**
+ * Resolves a claim path like "custom.nickname" or multiple alternatives separated by "|".
+ * Returns the first found string value, or null if none could be resolved.
+ */
+ public function getClaimValue(object|array $tokenPayload, string $claimPath, int $providerId): mixed {
+ if ($claimPath === '') {
+ return null;
+ }
+
+ // Check config if dot-notation resolution is enabled
+ $resolveDot = $this->providerService->getSetting($providerId, ProviderService::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING, '0') === '1';
+
+ if (!$resolveDot) {
+ // fallback to simple access
+ if (is_object($tokenPayload) && property_exists($tokenPayload, $claimPath)) {
+ return $tokenPayload->{$claimPath};
+ } elseif (is_array($tokenPayload) && array_key_exists($claimPath, $tokenPayload)) {
+ return $tokenPayload[$claimPath];
+ }
+ return null;
+ }
+
+ // Support alternatives separated by "|"
+ $alternatives = explode('|', $claimPath);
+
+ foreach ($alternatives as $altPath) {
+ $parts = explode('.', trim($altPath));
+ $value = $tokenPayload;
+
+ foreach ($parts as $part) {
+ if (is_object($value) && property_exists($value, $part)) {
+ $value = $value->{$part};
+ } elseif (is_array($value) && array_key_exists($part, $value)) {
+ $value = $value[$part];
+ } else {
+ continue 2;
+ }
+ }
+
+ if (is_string($value)) {
+ return $value;
+ }
+ }
+
+ return null;
+ }
/**
* @param string $tokenUserId
* @param int $providerId
@@ -72,64 +118,64 @@ public function provisionUser(string $tokenUserId, int $providerId, object $idTo
// get name/email/quota information from the token itself
$emailAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_EMAIL, 'email');
- $email = $idTokenPayload->{$emailAttribute} ?? null;
+ $email = $this->getClaimValue($idTokenPayload, $emailAttribute, $providerId);//$idTokenPayload->{$emailAttribute} ?? null;
$displaynameAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_DISPLAYNAME, 'name');
- $userName = $idTokenPayload->{$displaynameAttribute} ?? null;
+ $userName = $this->getClaimValue($idTokenPayload, $displaynameAttribute, $providerId);//$idTokenPayload->{$displaynameAttribute} ?? null;
$quotaAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_QUOTA, 'quota');
- $quota = $idTokenPayload->{$quotaAttribute} ?? null;
+ $quota = $this->getClaimValue($idTokenPayload, $quotaAttribute, $providerId);//$idTokenPayload->{$quotaAttribute} ?? null;
$languageAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_LANGUAGE, 'language');
- $language = $idTokenPayload->{$languageAttribute} ?? null;
+ $language = $this->getClaimValue($idTokenPayload, $languageAttribute, $providerId);//$idTokenPayload->{$languageAttribute} ?? null;
$genderAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_GENDER, 'gender');
- $gender = $idTokenPayload->{$genderAttribute} ?? null;
+ $gender = $this->getClaimValue($idTokenPayload, $genderAttribute, $providerId);//$idTokenPayload->{$genderAttribute} ?? null;
$addressAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_ADDRESS, 'address');
- $address = $idTokenPayload->{$addressAttribute} ?? null;
+ $address = $this->getClaimValue($idTokenPayload, $addressAttribute, $providerId);//$idTokenPayload->{$addressAttribute} ?? null;
$postalcodeAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_POSTALCODE, 'postal_code');
- $postalcode = $idTokenPayload->{$postalcodeAttribute} ?? null;
+ $postalcode = $this->getClaimValue($idTokenPayload, $postalcodeAttribute, $providerId);//$idTokenPayload->{$postalcodeAttribute} ?? null;
$streetAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_STREETADDRESS, 'street_address');
- $street = $idTokenPayload->{$streetAttribute} ?? null;
+ $street = $this->getClaimValue($idTokenPayload, $streetAttribute, $providerId);//$idTokenPayload->{$streetAttribute} ?? null;
$localityAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_LOCALITY, 'locality');
- $locality = $idTokenPayload->{$localityAttribute} ?? null;
+ $locality = $this->getClaimValue($idTokenPayload, $localityAttribute, $providerId);//$idTokenPayload->{$localityAttribute} ?? null;
$regionAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_REGION, 'region');
- $region = $idTokenPayload->{$regionAttribute} ?? null;
+ $region = $this->getClaimValue($idTokenPayload, $regionAttribute, $providerId);//$idTokenPayload->{$regionAttribute} ?? null;
$countryAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_COUNTRY, 'country');
- $country = $idTokenPayload->{$countryAttribute} ?? null;
+ $country = $this->getClaimValue($idTokenPayload, $countryAttribute, $providerId);//$idTokenPayload->{$countryAttribute} ?? null;
$websiteAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_WEBSITE, 'website');
- $website = $idTokenPayload->{$websiteAttribute} ?? null;
+ $website = $this->getClaimValue($idTokenPayload, $websiteAttribute, $providerId);//$idTokenPayload->{$websiteAttribute} ?? null;
$avatarAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_AVATAR, 'avatar');
- $avatar = $idTokenPayload->{$avatarAttribute} ?? null;
+ $avatar = $this->getClaimValue($idTokenPayload, $avatarAttribute, $providerId);//$idTokenPayload->{$avatarAttribute} ?? null;
$phoneAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_PHONE, 'phone_number');
- $phone = $idTokenPayload->{$phoneAttribute} ?? null;
+ $phone = $this->getClaimValue($idTokenPayload, $phoneAttribute, $providerId);//$idTokenPayload->{$phoneAttribute} ?? null;
$twitterAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_TWITTER, 'twitter');
- $twitter = $idTokenPayload->{$twitterAttribute} ?? null;
+ $twitter = $this->getClaimValue($idTokenPayload, $twitterAttribute, $providerId);//$idTokenPayload->{$twitterAttribute} ?? null;
$fediverseAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_FEDIVERSE, 'fediverse');
- $fediverse = $idTokenPayload->{$fediverseAttribute} ?? null;
+ $fediverse = $this->getClaimValue($idTokenPayload, $fediverseAttribute, $providerId);//$idTokenPayload->{$fediverseAttribute} ?? null;
$organisationAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_ORGANISATION, 'organisation');
- $organisation = $idTokenPayload->{$organisationAttribute} ?? null;
+ $organisation = $this->getClaimValue($idTokenPayload, $organisationAttribute, $providerId);//$idTokenPayload->{$organisationAttribute} ?? null;
$roleAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_ROLE, 'role');
- $role = $idTokenPayload->{$roleAttribute} ?? null;
+ $role = $this->getClaimValue($idTokenPayload, $roleAttribute, $providerId);//$idTokenPayload->{$roleAttribute} ?? null;
$headlineAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_HEADLINE, 'headline');
- $headline = $idTokenPayload->{$headlineAttribute} ?? null;
+ $headline = $this->getClaimValue($idTokenPayload, $headlineAttribute, $providerId);//$idTokenPayload->{$headlineAttribute} ?? null;
$biographyAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_BIOGRAPHY, 'biography');
- $biography = $idTokenPayload->{$biographyAttribute} ?? null;
+ $biography = $this->getClaimValue($idTokenPayload, $biographyAttribute, $providerId);//$idTokenPayload->{$biographyAttribute} ?? null;
$event = new AttributeMappedEvent(ProviderService::SETTING_MAPPING_UID, $idTokenPayload, $tokenUserId);
$this->eventDispatcher->dispatchTyped($event);
diff --git a/lib/User/Backend.php b/lib/User/Backend.php
index 2b4533bf..e7376897 100644
--- a/lib/User/Backend.php
+++ b/lib/User/Backend.php
@@ -17,6 +17,7 @@
use OCA\UserOIDC\Service\DiscoveryService;
use OCA\UserOIDC\Service\LdapService;
use OCA\UserOIDC\Service\ProviderService;
+use OCA\UserOIDC\Service\ProvisioningService;
use OCA\UserOIDC\User\Validator\SelfEncodedValidator;
use OCA\UserOIDC\User\Validator\UserInfoValidator;
use OCP\AppFramework\Db\DoesNotExistException;
@@ -56,6 +57,7 @@ public function __construct(
private DiscoveryService $discoveryService,
private ProviderMapper $providerMapper,
private ProviderService $providerService,
+ private ProvisioningService $provisioningService,
private LdapService $ldapService,
private IUserManager $userManager,
) {
@@ -175,22 +177,21 @@ private function formatUserData(int $providerId, array $attributes): array {
$result = ['formatted' => [], 'raw' => $attributes];
$emailAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_EMAIL, 'email');
- $result['formatted']['email'] = $attributes[$emailAttribute] ?? null;
+ $result['formatted']['email'] = $this->provisioningService->getClaimValue($attributes, $emailAttribute, $providerId);
$displaynameAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_DISPLAYNAME, 'name');
- $result['formatted']['displayName'] = $attributes[$displaynameAttribute] ?? null;
-
+ $result['formatted']['displayName'] = $this->provisioningService->getClaimValue($attributes, $displaynameAttribute, $providerId);
$quotaAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_QUOTA, 'quota');
- $result['formatted']['quota'] = $attributes[$quotaAttribute] ?? null;
+ $result['formatted']['quota'] = $this->provisioningService->getClaimValue($attributes, $quotaAttribute, $providerId);
if ($result['formatted']['quota'] === '') {
$result['formatted']['quota'] = 'default';
}
$groupsAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_GROUPS, 'groups');
- $result['formatted']['groups'] = $attributes[$groupsAttribute] ?? null;
+ $result['formatted']['groups'] = $this->provisioningService->getClaimValue($attributes, $groupsAttribute, $providerId);
$uidAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_UID, 'sub');
- $result['formatted']['uid'] = $attributes[$uidAttribute] ?? null;
+ $result['formatted']['uid'] = $this->provisioningService->getClaimValue($attributes, $uidAttribute, $providerId);
return $result;
}
diff --git a/lib/User/Validator/SelfEncodedValidator.php b/lib/User/Validator/SelfEncodedValidator.php
index ebcd3e2c..400751d0 100644
--- a/lib/User/Validator/SelfEncodedValidator.php
+++ b/lib/User/Validator/SelfEncodedValidator.php
@@ -12,6 +12,7 @@
use OCA\UserOIDC\Db\Provider;
use OCA\UserOIDC\Service\DiscoveryService;
use OCA\UserOIDC\Service\ProviderService;
+use OCA\UserOIDC\Service\ProvisioningService;
use OCA\UserOIDC\User\Provisioning\SelfEncodedTokenProvisioning;
use OCA\UserOIDC\Vendor\Firebase\JWT\JWT;
use OCP\AppFramework\Utility\ITimeFactory;
@@ -23,6 +24,7 @@ class SelfEncodedValidator implements IBearerTokenValidator {
public function __construct(
private DiscoveryService $discoveryService,
+ private ProvisioningService $provisioningService,
private LoggerInterface $logger,
private ITimeFactory $timeFactory,
private IConfig $config,
@@ -32,7 +34,8 @@ public function __construct(
public function isValidBearerToken(Provider $provider, string $bearerToken): ?string {
/** @var ProviderService $providerService */
$providerService = \OC::$server->get(ProviderService::class);
- $uidAttribute = $providerService->getSetting($provider->getId(), ProviderService::SETTING_MAPPING_UID, ProviderService::SETTING_MAPPING_UID_DEFAULT);
+ $providerId = $provider->getId();
+ $uidAttribute = $providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_UID, ProviderService::SETTING_MAPPING_UID_DEFAULT);
// try to decode the bearer token
JWT::$leeway = 60;
@@ -73,11 +76,8 @@ public function isValidBearerToken(Provider $provider, string $bearerToken): ?st
}
// find the user ID
- if (!isset($payload->{$uidAttribute})) {
- return null;
- }
-
- return $payload->{$uidAttribute};
+ $uid = $this->provisioningService->getClaimValue($payload, $uidAttribute, $providerId);
+ return $uid ?: null;
}
public function getProvisioningStrategy(): string {
diff --git a/lib/User/Validator/UserInfoValidator.php b/lib/User/Validator/UserInfoValidator.php
index f261b4ec..fd36a08c 100644
--- a/lib/User/Validator/UserInfoValidator.php
+++ b/lib/User/Validator/UserInfoValidator.php
@@ -12,23 +12,24 @@
use OCA\UserOIDC\Db\Provider;
use OCA\UserOIDC\Service\OIDCService;
use OCA\UserOIDC\Service\ProviderService;
+use OCA\UserOIDC\Service\ProvisioningService;
class UserInfoValidator implements IBearerTokenValidator {
public function __construct(
private OIDCService $userInfoService,
private ProviderService $providerService,
+ private ProvisioningService $provisioningService,
) {
}
public function isValidBearerToken(Provider $provider, string $bearerToken): ?string {
$userInfo = $this->userInfoService->userinfo($provider, $bearerToken);
- $uidAttribute = $this->providerService->getSetting($provider->getId(), ProviderService::SETTING_MAPPING_UID, ProviderService::SETTING_MAPPING_UID_DEFAULT);
- if (!isset($userInfo[$uidAttribute])) {
- return null;
- }
-
- return $userInfo[$uidAttribute];
+ $providerId = $provider->getId();
+ $uidAttribute = $this->providerService->getSetting($providerId, ProviderService::SETTING_MAPPING_UID, ProviderService::SETTING_MAPPING_UID_DEFAULT);
+ // find the user ID
+ $uid = $this->provisioningService->getClaimValue($userInfo, $uidAttribute, $providerId);
+ return $uid ?: null;
}
public function getProvisioningStrategy(): string {
diff --git a/src/components/SettingsForm.vue b/src/components/SettingsForm.vue
index 5c84a250..874af2a0 100644
--- a/src/components/SettingsForm.vue
+++ b/src/components/SettingsForm.vue
@@ -67,6 +67,9 @@
placeholder="claim1 claim2 claim3">
{{ t('user_oidc', 'Attribute mapping') }}
+
+ {{ t('user_oidc', 'Enable nested and fallback claim mappings (like "{example}")', { example: 'custom.nickname | profile.name | name' }) }}
+
true,
'groupWhitelistRegex' => '1',
'restrictLoginToGroups' => true,
+ 'nestedAndFallbackClaims' => true,
],
],
[
@@ -133,6 +134,7 @@ public function testGetProvidersWithSettings() {
'groupProvisioning' => true,
'groupWhitelistRegex' => '1',
'restrictLoginToGroups' => true,
+ 'nestedAndFallbackClaims' => true,
],
],
], $this->providerService->getProvidersWithSettings());
@@ -171,6 +173,7 @@ public function testSetSettings() {
'mappingGender' => 'gender',
'groupWhitelistRegex' => '',
'restrictLoginToGroups' => false,
+ 'nestedAndFallbackClaims' => false,
];
$this->config->expects(self::any())
->method('getAppValue')
@@ -206,6 +209,7 @@ public function testSetSettings() {
[Application::APP_ID, 'provider-1-' . ProviderService::SETTING_GROUP_PROVISIONING, '', '1'],
[Application::APP_ID, 'provider-1-' . ProviderService::SETTING_GROUP_WHITELIST_REGEX, '', ''],
[Application::APP_ID, 'provider-1-' . ProviderService::SETTING_RESTRICT_LOGIN_TO_GROUPS, '', '0'],
+ [Application::APP_ID, 'provider-1-' . ProviderService::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING, '', '0'],
]);
Assert::assertEquals(
diff --git a/tests/unit/Service/ProvisioningServiceTest.php b/tests/unit/Service/ProvisioningServiceTest.php
index bf3369c8..3d449e6d 100644
--- a/tests/unit/Service/ProvisioningServiceTest.php
+++ b/tests/unit/Service/ProvisioningServiceTest.php
@@ -143,6 +143,7 @@ public function testProvisionUserAutoProvisioning(): void {
[$providerId, ProviderService::SETTING_MAPPING_BIOGRAPHY, 'biography', 'biography'],
[$providerId, ProviderService::SETTING_MAPPING_PHONE, 'phone_number', 'phone_number'],
[$providerId, ProviderService::SETTING_MAPPING_GENDER, 'gender', 'gender'],
+ [$providerId, ProviderService::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING, '0', '0'],
]
));
@@ -214,6 +215,7 @@ public function testProvisionUserInvalidProperties(): void {
[$providerId, ProviderService::SETTING_MAPPING_BIOGRAPHY, 'biography', 'biography'],
[$providerId, ProviderService::SETTING_MAPPING_PHONE, 'phone_number', 'phone_number'],
[$providerId, ProviderService::SETTING_MAPPING_GENDER, 'gender', 'gender'],
+ [$providerId, ProviderService::SETTING_RESOLVE_NESTED_AND_FALLBACK_CLAIMS_MAPPING, '0', '0'],
]
));
@@ -257,7 +259,7 @@ public function testProvisionUserInvalidProperties(): void {
->method('getProperty')
->with('twitter')
->willReturn($property);
-
+
$this->accountManager->expects(self::once())
->method('getAccount')