medusajs/medusa · error · MedusaError

OIDC does not support registration. Use method `authenticate

Error message

OIDC does not support registration. Use method `authenticate` instead.

What it means

The OIDC provider implements only the authenticate flow because user identity originates from the external identity provider; the register method is deliberately unsupported and throws NOT_ALLOWED with a pointer to authenticate.

Source

Thrown at packages/modules/providers/auth-oidc/src/services/oidc.ts:76

  constructor(
    { logger, cache }: InjectedDependencies,
    options: OidcAuthProviderOptions
  ) {
    // @ts-ignore
    super(...arguments)
    this.config_ = options
    this.logger_ = logger
    this.engine_ = new OidcEngine(options, cache)
  }

  // The same OIDC package is registered once per IdP (okta, auth0, ...), so the
  // display name is instance-specific.
  get displayName() {
    return this.config_.display_name ?? OidcAuthService.DISPLAY_NAME
  }

  async register(_: AuthenticationInput): Promise<AuthenticationResponse> {
    throw new MedusaError(
      MedusaError.Types.NOT_ALLOWED,
      "OIDC does not support registration. Use method `authenticate` instead."
    )
  }

  async authenticate(
    req: AuthenticationInput,
    authIdentityService: AuthIdentityProviderService
  ): Promise<AuthenticationResponse> {
    const body: Record<string, string> = req.body ?? {}

    const callbackUrl = body?.callback_url ?? this.config_.callback_url

    // The allowlist is opt-in: when it isn't configured, validating the callback
    // URL is left entirely to the identity provider.
    const allowedCallbackUrls = this.config_.allowed_callback_urls

    if (

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Remove or guard the register call for OIDC strategies — use authenticate (i.e. GET /auth/customer/<provider-id> to start the redirect flow).
  2. If you need signup semantics, they belong on the IdP side; after callback, complete registration with the auth callback/refresh-token routes as with other third-party strategies.
  3. In shared route code, check the provider id/type before calling register.

Example fix

// before
const result = await provider.register(credentials)
// after
const result = await provider.authenticate(credentials) // OIDC has no registration; identity comes from the IdP
Defensive patterns

Strategy: type-guard

Validate before calling

const canRegister = (p: { register?: unknown }): boolean =>
  typeof p.register === "function" && p.constructor?.name !== "OidcAuthService"

Type guard

const supportsRegistration = (provider: unknown): provider is { register(input: AuthenticationInput): Promise<AuthenticationResponse> } =>
  typeof (provider as { register?: unknown })?.register === "function" &&
  !(provider instanceof (require("@medusajs/auth-oidc").OidcAuthService ?? class {}))

Try / catch

try { await provider.register(input) } catch (e) { if (e instanceof MedusaError && e.type === MedusaError.Types.NOT_ALLOWED) { /* fall back to authenticate */ } throw e }

Prevention

When it happens

Trigger: Anything invoking the provider's register() — e.g. a custom auth route calling authProvider.register(...), or framework code routing a /auth/customer/<strategy>/register request to an OIDC strategy.

Common situations: Frontend or route code that generically supports emailpass strategies and assumes register exists for all providers; a middleware that branches to register for first-time users; copy-pasted route handlers from a password-based strategy.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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