{"record":{"id":"fd36a60235541b65","repo":"BookStackApp/BookStack","slug":"errors-oidc-no-email-address","errorCode":null,"errorMessage":"errors.oidc_no_email_address","messagePattern":"errors\\.oidc_no_email_address","errorType":"exception","errorClass":"OidcException","httpStatus":null,"severity":"error","filePath":"app/Access/Oidc/OidcService.php","lineNumber":210,"sourceCode":"        ]);\n\n        if (!is_null($returnClaims)) {\n            $idToken->replaceClaims($returnClaims);\n        }\n\n        if ($this->config()['dump_user_details']) {\n            throw new JsonDebugException($idToken->getAllClaims());\n        }\n\n        try {\n            $idToken->validate($settings->clientId);\n        } catch (OidcInvalidTokenException $exception) {\n            throw new OidcException(\"ID token validation failed with error: {$exception->getMessage()}\");\n        }\n\n        $userDetails = $this->getUserDetailsFromToken($idToken, $accessToken, $settings);\n        if (empty($userDetails->email)) {\n            throw new OidcException(trans('errors.oidc_no_email_address'));\n        }\n        if (empty($userDetails->name)) {\n            $userDetails->name = $userDetails->externalId;\n        }\n\n        $isLoggedIn = auth()->check();\n        if ($isLoggedIn) {\n            throw new OidcException(trans('errors.oidc_already_logged_in'));\n        }\n\n        try {\n            $user = $this->registrationService->findOrRegister(\n                $userDetails->name,\n                $userDetails->email,\n                $userDetails->externalId\n            );\n        } catch (UserRegistrationException $exception) {\n            throw new OidcException($exception->getMessage());","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/Oidc/OidcService.php#L192-L228","documentation":"BookStack requires an email address to link/match an OIDC login to a local user. When the ID token and userinfo response together yield an empty email, this OidcException with the translated 'errors.oidc_no_email_address' message is thrown and login aborts.","triggerScenarios":"processAccessTokenCallback calls getUserDetailsFromToken; the resulting userDetails->email is empty because the IdP's ID token/userinfo omit the email claim, or BOOKSTACK_OIDC_END_SESSION... specifically the email_claim config points at a claim the IdP does not send.","commonSituations":"IdP not configured to release the email scope/claim (common with Azure AD, Keycloak, Authentik defaults), or custom external_id_claim/email claim misconfigured in .env.","solutions":["Ensure the 'email' and 'profile'/'openid' scopes are requested and granted by the IdP client","Check the IdP user actually has an email set and the client is allowed to read it","If the email lives in a nonstandard claim, set OIDC_EMAIL_CLAIM (email_claim config) to that claim name","Review getUserDetailsFromToken flow: if userinfo endpoint is enabled, confirm it returns email"],"exampleFix":"// before\n# no email claim configured, IdP omits email\n// after (.env)\nOIDC_AUTH_ENDPOINT=...\nOIDC_ADDITIONAL_SCOPES=email profile\nOIDC_EMAIL_CLAIM=email","handlingStrategy":"validation","validationCode":"// Confirm the IdP releases email before relying on OIDC login:\ncurl -s -H \"Authorization: Bearer $ACCESS_TOKEN\" https://idp.example.com/userinfo | jq -e '.email != null and .email != \"\"'\n// And in .env ensure scopes include email:\n// OIDC_ADDITIONAL_SCOPES=\"email profile\"","typeGuard":null,"tryCatchPattern":"try {\n    auth()->attemptOidcLogin();\n} catch (BookStack\\Access\\Oidc\\OidcException $e) {\n    if (trans('errors.oidc_no_email_address') === $e->getMessage()) {\n        abort(400, 'Identity provider did not return an email claim; enable email scope/claim at the IdP');\n    }\n    throw $e;\n}","preventionTips":["Always request the 'email' scope in the OIDC client config","Ensure every IdP user has a non-empty email and the client may read it","Set OIDC_EMAIL_CLAIM if your IdP stores email in a nonstandard claim","Test with a fresh IdP user, not an admin account with extra claims"],"tags":["oidc","email","user-attributes"],"backgroundTag":"missing-email-claim","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}