Auth zitadel
Zitadel (OIDC) authentication provider for Medusa v2
medusa-auth-zitadel
Zitadel authentication provider for Medusa v2.
A standalone Auth Module Provider that lets customers, admin users, or custom actor types log in with Zitadel using the OpenID Connect Authorization Code flow.
Zitadel endpoints are resolved through OIDC Discovery (), so the provider works with Zitadel Cloud and self-hosted instances behind a custom domain. The returned is verified cryptographically against Zitadel's JWKS.
Requirements
- Medusa v2 ( ^2.x)
- Node.js 20+
- A running Zitadel instance (Cloud or self-hosted)
Installation
Zitadel setup
- In your Zitadel instance, create (or open) a Project.
- Add a new application:
- Type: Web
- Authentication method: Code — this uses , matching the provider's default.
- Set the Redirect URI to exactly the you will configure below (e.g. ). It must match character for character — Zitadel rejects any mismatch during the token exchange.
- Copy the generated Client ID and Client Secret.
Configuration
Register the provider in the Auth Module's array in :
The () is the value used in authentication route paths.
Options
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
| Yes | — | Zitadel issuer URL, e.g. . Trailing slashes are normalised. | ||
| Yes | — | OIDC client ID of the Zitadel application. | ||
| Yes | — | OIDC client secret of the Zitadel application. | ||
| Yes | — | URL Zitadel redirects to after authentication. Can be overridden per request with a body parameter. | ||
| No | Scopes requested from Zitadel. | |||
| No | How the client authenticates at the token endpoint. Must match the Zitadel application's authentication method. |
Environment variables
| Variable | Maps to |
|---|---|
Actor types
By default only the actor type is restricted to ; other actor types can authenticate with any installed provider. To control which providers each actor type may use, set . Note that specifying this option overrides the default, so any actor type you omit can no longer authenticate with any provider:
Authentication flow
The provider implements the standard Medusa third-party authentication flow. Replace with your actor type (, , or a custom actor type).
1. Start the flow. The storefront asks Medusa for the Zitadel authorize URL:
The response contains a property — the Zitadel authorize URL. Redirect the browser to it. Omit to use the configured .
2. Zitadel redirects back. After the user authenticates, Zitadel redirects the browser to your with . The storefront forwards both to Medusa:
3. Receive the Medusa token. On success, Medusa returns a JWT and the auth identity:
Use as the header for authenticated store or admin requests. If the auth identity does not exist yet, the provider creates it on first successful login.
The provider's value (containing the callback URL used as ) is stored server-side via the Auth Module and consumed on callback, which protects the flow against CSRF and session replay.
Claim mapping
Zitadel's claims are mapped into Medusa's auth identity as follows.
| Zitadel claim | Medusa field |
|---|---|
Only claims actually returned by Zitadel are stored.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
| is wrong or unreachable. It must be the Zitadel base domain, e.g. — not the token or authorize endpoint. | |
| The returned by discovery differs from your setting (Zitadel may add or omit a trailing slash, or you are using a different hostname than the one Zitadel self-reports). Use the issuer exactly as Zitadel reports it. | |
| Usually a redirect-URI mismatch. The must exactly match a Redirect URI registered on the Zitadel application, including scheme, host, and path. | |
| does not match the Zitadel application's authentication method. Zitadel Web apps default to ; if you configured Post, set . | |
| The audience or issuer did not match. Confirm belongs to the Zitadel application you are authenticating against. | |
| Expected. Zitadel SSO requires users to be provisioned in Zitadel first; there is no registration route. | |
| User can authenticate in Zitadel but gets a Medusa 401 | The actor type is not allowed to use . Check . |
Publishing
For maintainers, from the repository root:
The script runs the build automatically. After publishing, submit the package to the Medusa Integrations directory.
License
MIT

