medusajs/medusa · error · MedusaError

The identity provider did not confirm a verified email addre

Error message

The identity provider did not confirm a verified email address

What it means

By default (require_verified_email defaults to true), the engine requires claims.email_verified === true in the ID token. If the IdP does not assert a verified email, authentication is rejected with INVALID_DATA even though the token itself is valid.

Source

Thrown at packages/modules/providers/auth-oidc/src/engine/engine.ts:231

    const entityIdValue = claims[entityIdClaim]

    if (
      entityIdValue === undefined ||
      entityIdValue === null ||
      entityIdValue === ""
    ) {
      throw new MedusaError(
        MedusaError.Types.INVALID_DATA,
        `The identity provider's ID token is missing the '${entityIdClaim}' claim used to identify the user`
      )
    }

    const emailClaim = mappings.email ?? "email"
    const email = claims[emailClaim]

    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"

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Verify/confirm the user's email in the identity provider so it asserts email_verified: true.
  2. If your IdP does not track verification and you accept that risk, set require_verified_email: false in the provider options.
  3. Ensure the standard 'email' scope is requested so email/email_verified are emitted, and that a custom email mapping has a matching verified claim path.

Example fix

// before
options: { issuer: "...", client_id: "...", callback_url: "..." } // defaults to requiring verified email
// after
options: { issuer: "...", client_id: "...", callback_url: "...", require_verified_email: false }
Defensive patterns

Strategy: validation

Validate before calling

const requireVerified = options.require_verified_email ?? true
if (requireVerified) {
  // verify in the IdP that your test users have confirmed emails
  // or explicitly opt out: require_verified_email: false
}

Type guard

const isVerifiedEmail = (claims: Record<string, unknown>): boolean =>
  claims.email_verified === true

Try / catch

try { engine.mapClaims(claims) } catch (e) { if (e instanceof MedusaError && /verified email/.test(e.message)) { /* prompt user to verify email at IdP, or disable requirement */ } throw e }

Prevention

When it happens

Trigger: The IdP emits email but not email_verified (common with some providers/mappers); email_verified is false or a non-boolean truthy value; the email claim mapping points at a custom claim without a corresponding verified flag.

Common situations: Keycloak or self-hosted IdPs where email verification is not enforced so the claim is absent; development/test users created directly in the IdP admin without verified email; custom email claim mapping that bypasses the standard email_verified claim.

Related errors


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/d1e37c7cc1355b98. Report an issue: GitHub.