medusajs/medusa · error · MedusaError
UNAUTHORIZED
UNAUTHORIZED
Error message
Only ${authProvider} identities can create a user account for this authentication context What it means
Thrown when the auth identity resolved from the token does not have exactly one provider identity, or that provider identity's provider does not match the :auth_provider in the URL. The route only allows creating a user through the same provider that authenticated the request. Maps to HTTP 401 (UNAUTHORIZED).
Source
Thrown at packages/medusa/src/api/auth/[auth_provider]/user/route.ts:52
"Email is required to create a user account."
)
}
// Check that the auth identity was created by the provider named in the route.
const providerIdentities = await query
.graph({
entity: "auth_identity",
fields: ["id", "provider_identities.provider"],
filters: {
id: req.auth_context.auth_identity_id,
},
})
.then((result) => result.data[0]?.provider_identities)
if (
providerIdentities?.length !== 1 ||
providerIdentities[0].provider !== authProvider
) {
throw new MedusaError(
MedusaError.Types.UNAUTHORIZED,
`Only ${authProvider} identities can create a user account for this authentication context`
)
}
// Check if a user already exists for the identity-provider-verified email.
const user = await query
.graph({
entity: "user",
fields: ["id"],
filters: {
email: req.auth_context.user_metadata.email,
},
})
.then((result) => result.data[0])
// Link path: an existing user with a matching email is linked.
if (user) {View on GitHub (pinned to 5e06e544a2)
Solutions
- Use the same provider in the URL as the one used to obtain the JWT
- Inspect the auth identity's provider_identities (query auth provider identity) to confirm exactly one exists
- Unlink extra provider identities if multiple are attached
- Re-authenticate with the intended provider to mint a matching token
Example fix
// before
const token = await sdk.auth.authenticate('emailpass', {...})
await fetch('/auth/google/user', { headers: { Authorization: `Bearer ${token}` }, method: 'POST' })
// after
await fetch('/auth/emailpass/user', { headers: { Authorization: `Bearer ${token}` }, method: 'POST' }) Defensive patterns
Strategy: validation
Validate before calling
const claims = parseJwt(token)
const urlProvider = providerUsedToAuthenticate // track alongside token
if (claims.auth_provider !== urlProvider) throw new Error('provider mismatch') Try / catch
catch (e) { if (e.type === 'unauthorized' && /identities can create/.test(e.message)) retryWithCorrectProvider() else throw e } Prevention
- Derive the URL provider segment from the auth flow, never hard-code it
- Store which provider minted the token alongside it
- Keep identities single-provider during signup flows
When it happens
Trigger: Calling POST /auth/google/user with a token minted via emailpass; an identity that has zero or multiple provider identities (e.g. identity linked to two providers).
Common situations: Mismatch between URL provider segment and the provider actually used to authenticate; identities progressively linked to multiple providers; copy-pasted route from another provider's flow.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Verification code does not belong to provider "${data.code_p
- Invalid token
- Customer with this email already has an account
- The user is already authenticated and cannot accept an invit
- User ID not found
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/d67d5aa00afff364.
Report an issue: GitHub.