medusajs/medusa · error · MedusaError
The email domain is not allowed to authenticate with this pr
Error message
The email domain is not allowed to authenticate with this provider
What it means
When allowed_email_domains is configured, the engine extracts the domain from the mapped email claim and checks membership in the allow-list. An email with no parseable domain or a domain not in the list is rejected with UNAUTHORIZED.
Source
Thrown at packages/modules/providers/auth-oidc/src/engine/engine.ts:247
const requireVerifiedEmail = this.options_.require_verified_email ?? true
if (requireVerifiedEmail && claims.email_verified !== true) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"The identity provider did not confirm a verified email address"
)
}
if (this.options_.allowed_email_domains?.length) {
const allowedDomains = this.options_.allowed_email_domains.map((domain) =>
domain.toLowerCase()
)
const domain =
typeof email === "string"
? email.split("@")[1]?.toLowerCase()
: undefined
if (!domain || !allowedDomains.includes(domain)) {
throw new MedusaError(
MedusaError.Types.UNAUTHORIZED,
"The email domain is not allowed to authenticate with this provider"
)
}
}
const userMetadata: Record<string, unknown> = {}
for (const [field, claimName] of Object.entries(mappings)) {
if (field === "entity_id" || !claimName) {
continue
}
if (isDefined(claims[claimName])) {
userMetadata[field] = claims[claimName]
}
}
return {
entityId: String(entityIdValue),View on GitHub (pinned to 5e06e544a2)
Solutions
- Add the user's domain (lowercase, exact) to allowed_email_domains in the provider options.
- For subdomain support, list each subdomain explicitly — the check is an exact match, not suffix-based.
- If the restriction is unintended, remove the allowed_email_domains option entirely.
Example fix
// before
options: { ..., allowed_email_domains: ["acme.com"] }
// after
options: { ..., allowed_email_domains: ["acme.com", "sub.acme.com"] } Defensive patterns
Strategy: validation
Validate before calling
const domain = email?.split("@")[1]?.toLowerCase()
if (allowedDomains.length && !allowedDomains.includes(domain)) {
return res.status(403).json({ error: "email_domain_not_allowed" })
} Type guard
const isAllowedDomain = (email: string | undefined, allowed: string[]): boolean =>
!!email && allowed.includes(email.split("@")[1]?.toLowerCase() ?? "") Try / catch
try { engine.mapClaims(claims) } catch (e) { if (e instanceof MedusaError && e.type === MedusaError.Types.UNAUTHORIZED && /domain is not allowed/.test(e.message)) { res.status(403).json({ error: "email_domain_not_allowed" }); return } throw e } Prevention
- List domains lowercase and include each subdomain explicitly (exact match only).
- Surface a clear 'use your company account' message in the UI for this case.
- Review the allow-list whenever the company domain changes.
When it happens
Trigger: allowed_email_domains: ["acme.com"] is set and a user authenticates with user@gmail.com, or the mapped email claim is not a string so no domain can be extracted.
Common situations: Restricting a corporate SSO to company domains and users try personal addresses; the allow-list entries have different casing or subdomains (sub.acme.com vs acme.com — only exact lowercase match passes); test users provisioned with an email outside the list.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Forbidden
- id_token is missing 'sub' claim
- OIDC engine requires an 'issuer' option
- OIDC engine requires a 'client_id' option
- OIDC engine requires a 'callback_url' option
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/8055a7ed010e0d8c.
Report an issue: GitHub.