{"record":{"id":"4da3a06bd4cccb23","repo":"passbolt/passbolt_api","slug":"single-sign-on-failed-the-0-claim-is-not-present-please-4da3a0","errorCode":null,"errorMessage":"Single sign-on failed. The {0} claim is not present, please contact your administrator.","messagePattern":"Single sign-on failed\\. The (.+?) claim is not present, please contact your administrator\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/Sso/src/Utility/Azure/ResourceOwner/AzureResourceOwner.php","lineNumber":70,"sourceCode":"     * @return string|null\n     */\n    public function getId(): ?string\n    {\n        return $this->data['oid'] ?? null;\n    }\n\n    /**\n     * Retrieves email of the resource owner.\n     *\n     * @return string\n     * @throws \\Cake\\Http\\Exception\\BadRequestException When email alias field is not present in the data.\n     */\n    public function getEmail(): string\n    {\n        if (!isset($this->data[$this->emailAliasField]) || is_null($this->data[$this->emailAliasField])) {\n            $msg = __('Single sign-on failed.') . ' ';\n            $msg .= __('The {0} claim is not present, please contact your administrator.', $this->emailAliasField);\n            throw new BadRequestException($msg);\n        }\n\n        return $this->data[$this->emailAliasField];\n    }\n\n    /**\n     * Returns all the data obtained about the user.\n     *\n     * @return array\n     */\n    public function toArray(): array\n    {\n        return $this->data;\n    }\n\n    /**\n     * @inheritDoc\n     */","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Utility/Azure/ResourceOwner/AzureResourceOwner.php#L52-L88","documentation":"AzureResourceOwner::getEmail() throws a BadRequestException when the configured email alias claim (emailAliasField, e.g. 'email', 'upn' or 'preferred_username') is missing or null in the Azure AD token/resource-owner payload. Passbolt needs an email to match the Azure identity to a local user, so SSO cannot proceed without that claim. It is an administrator-side configuration/tenant issue rather than a user mistake.","triggerScenarios":"OAuth2/OpenID callback for Azure SSO calls getEmail() on the resource owner; the decoded ID token lacks the configured alias claim — e.g. Azure tenant admin removed the 'email' optional claim, user has no mail attribute, or passbolt is configured to use 'preferred_username'/'upn' but the token was issued without those claims.","commonSituations":"Azure AD tenants where the email claim is not emitted by default (personal accounts or service principals); admins switching email alias field in passbolt SSO settings without updating Azure optional-claims configuration; test accounts without a mail address.","solutions":["Check which email alias field passbolt expects and inspect the decoded token payload (toArray()) to see which claims Azure actually returned.","In Azure Portal, configure the app registration's token configuration (optional claims) to include 'email' (or the configured alias, e.g. 'upn'/'preferred_username') in ID tokens.","Verify the Azure user account has a verified mail/upn attribute.","If passbolt setting uses an alias the tenant cannot provide, change the SSO email claim setting to a claim Azure actually emits.","Ask users to authenticate with their organizational account rather than a personal/personal-Teams account."],"exampleFix":"// before (Azure app registration lacks optional claims)\n// token payload: { \"aud\": \"...\", \"oid\": \"...\" } // no 'email' => getEmail() throws\n// after: Azure Portal -> App registrations -> Token configuration -> Add optional claim: email (ID token)\n// token payload now: { \"aud\": \"...\", \"oid\": \"...\", \"email\": \"user@corp.com\" }","handlingStrategy":"try-catch","validationCode":"$data = $resourceOwner->toArray();\nif (!isset($data[$emailAliasField]) || $data[$emailAliasField] === null) {\n    // surface admin-facing error before calling getEmail()\n}","typeGuard":"function hasEmailClaim(array $data, string $field): bool {\n    return isset($data[$field]) && is_string($data[$field]) && $data[$field] !== '';\n}","tryCatchPattern":"try {\n    $email = $resourceOwner->getEmail();\n} catch (\\Cake\\Http\\Exception\\BadRequestException $e) {\n    $this->log($e->getMessage());\n    return $this->renderError('sso', 'Email claim missing in Azure token; check token configuration.');\n}","preventionTips":["Configure Azure optional claims (email) on the app registration before enabling SSO","Match passbolt's email alias setting to a claim the tenant actually emits","Test with a real organizational account whose mail attribute is populated","Log resourceOwner->toArray() in a staging environment to inspect actual claims"],"tags":["sso","azure","oauth2","missing-claim","configuration"],"backgroundTag":"unexpected-response-shape","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}