BookStackApp/BookStack · error · OidcException
errors.oidc_no_email_address
Error message
errors.oidc_no_email_address
What it means
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.
Source
Thrown at app/Access/Oidc/OidcService.php:210
]);
if (!is_null($returnClaims)) {
$idToken->replaceClaims($returnClaims);
}
if ($this->config()['dump_user_details']) {
throw new JsonDebugException($idToken->getAllClaims());
}
try {
$idToken->validate($settings->clientId);
} catch (OidcInvalidTokenException $exception) {
throw new OidcException("ID token validation failed with error: {$exception->getMessage()}");
}
$userDetails = $this->getUserDetailsFromToken($idToken, $accessToken, $settings);
if (empty($userDetails->email)) {
throw new OidcException(trans('errors.oidc_no_email_address'));
}
if (empty($userDetails->name)) {
$userDetails->name = $userDetails->externalId;
}
$isLoggedIn = auth()->check();
if ($isLoggedIn) {
throw new OidcException(trans('errors.oidc_already_logged_in'));
}
try {
$user = $this->registrationService->findOrRegister(
$userDetails->name,
$userDetails->email,
$userDetails->externalId
);
} catch (UserRegistrationException $exception) {
throw new OidcException($exception->getMessage());View on GitHub (pinned to 18f8469a1c)
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
Example fix
// before # no email claim configured, IdP omits email // after (.env) OIDC_AUTH_ENDPOINT=... OIDC_ADDITIONAL_SCOPES=email profile OIDC_EMAIL_CLAIM=email
Defensive patterns
Strategy: validation
Validate before calling
// Confirm the IdP releases email before relying on OIDC login: curl -s -H "Authorization: Bearer $ACCESS_TOKEN" https://idp.example.com/userinfo | jq -e '.email != null and .email != ""' // And in .env ensure scopes include email: // OIDC_ADDITIONAL_SCOPES="email profile"
Try / catch
try {
auth()->attemptOidcLogin();
} catch (BookStack\Access\Oidc\OidcException $e) {
if (trans('errors.oidc_no_email_address') === $e->getMessage()) {
abort(400, 'Identity provider did not return an email claim; enable email scope/claim at the IdP');
}
throw $e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- errors.email_already_confirmed
- Token audience value has ' . count($aud) . ' values, Expecte
- Token authorized party exists but does not match the expecte
- Missing token expiration time value
- Token has expired
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/fd36a60235541b65.
Report an issue: GitHub.