Zitadel SSO with openZro Self-Hosted (Advanced)

Zitadel is an open-source identity infrastructure platform designed for cloud-native environments. It provides multi-tenancy, customizable branding, passwordless authentication, and supports protocols like OpenID Connect, OAuth2, SAML2, and LDAP.

Standalone Setup (Advanced)

This guide wires Zitadel as openZro's only identity provider — Dex is disabled and the management daemon talks directly to Zitadel for both token validation and user lifecycle. Choose this path only if all three apply:

  1. Zitadel is the source of truth for user lifecycle. You want openZro to call Zitadel's management API to list, invite, and delete users — so deleting a user in openZro removes them from Zitadel too. The recommended setup (Management Setup) only consumes tokens; it cannot write back.
  2. You need just one IdP, and it's Zitadel. This path doesn't support multiple upstreams — there's no Dex to aggregate them.
  3. You're willing to give up the bootstrap admin fallback. No embedded local user store. If Zitadel is down or misconfigured, nobody can log into the dashboard.

For everyone else — multi-IdP shops, anyone wanting a static admin fallback, or operators who only need authentication (not user lifecycle writeback) — use the Management Setup (Recommended) in the main Zitadel documentation instead.

Prerequisites

  • Zitadel instance (cloud or self-hosted) with SSL
  • Docker and Docker Compose for openZro

Step 1: Create and Configure Zitadel Application

  1. Navigate to Zitadel console
  2. Click Projects at the top menu, then click Create New Project
  3. Fill in:
    • Name: OPENZRO

New project

  1. Click Projects and select OPENZRO project
  2. Click New in Applications section
  3. Fill in:
    • Name: openzro
    • Type of Application: User Agent

New application

  1. Click Continue and set:
    • Authentication Method: PKCE

Application auth

  1. Click Continue and configure:
    • Redirect URIs:
      • https://<domain>/auth
      • https://<domain>/silent-auth
      • http://localhost:53000
    • Post Logout URIs: https://<domain>/

Application URIs

  1. Click Create and then Close
  2. Under Grant Types, select Authorization Code, Device Code, and Refresh Token
  3. Click Save

Application overview

  1. Copy Client ID for later use

Step 2: Configure Token Settings

  1. Select the openzro application
  2. Click Token Settings in the left menu
  3. Configure:
    • Auth Token Type: JWT
    • Check Add user roles to the access token
  4. Click Save

Token settings

Step 3: Configure Redirect Settings (Development Only)

  1. Click Redirect Settings in the left menu
  2. Toggle Development Mode
  3. Click Save

Redirect settings

Step 4: Create Service User

  1. Click Users in the top menu
  2. Select Service Users tab
  3. Click New
  4. Fill in:
    • User Name: openzro
    • Name: openzro
    • Description: openZro Service User
    • Access Token Type: JWT
  5. Click Create

Create service user

  1. Click Actions in the top right corner
  2. Click Generate Client Secret
  3. Copy ClientSecret for later use

Service user secret

Step 5: Grant User Manager Role

  1. Click Organization in the top menu
  2. Click + in the top right corner
  3. Search for openzro service user
  4. Check Org User Manager checkbox
  5. Click Add

Service account role

Step 6: Configure openZro

Your authority OIDC configuration will be available at:

https://<YOUR_ZITADEL_HOST_AND_PORT>/.well-known/openid-configuration

Set properties in the setup.env file:

OPENZRO_AUTH_OIDC_CONFIGURATION_ENDPOINT="https://<YOUR_ZITADEL_HOST_AND_PORT>/.well-known/openid-configuration"
OPENZRO_USE_AUTH0=false
OPENZRO_AUTH_CLIENT_ID="<CLIENT_ID>"
OPENZRO_AUTH_SUPPORTED_SCOPES="openid profile email offline_access api"
OPENZRO_AUTH_AUDIENCE="<CLIENT_ID>"
OPENZRO_AUTH_REDIRECT_URI="/auth"
OPENZRO_AUTH_SILENT_REDIRECT_URI="/silent-auth"

OPENZRO_AUTH_DEVICE_AUTH_PROVIDER="hosted"
OPENZRO_AUTH_DEVICE_AUTH_CLIENT_ID="<CLIENT_ID>"
OPENZRO_AUTH_DEVICE_AUTH_AUDIENCE="<CLIENT_ID>"

OPENZRO_MGMT_IDP="zitadel"
OPENZRO_IDP_MGMT_CLIENT_ID="openzro"
OPENZRO_IDP_MGMT_CLIENT_SECRET="<CLIENT_SECRET>"
OPENZRO_IDP_MGMT_EXTRA_MANAGEMENT_ENDPOINT="https://<YOUR_ZITADEL_HOST_AND_PORT>/management/v1"
OPENZRO_MGMT_IDP_SIGNKEY_REFRESH=true

Step 7: Continue with openZro Setup

You've configured all required resources in Zitadel. Continue with the openZro Self-hosting Guide.


Migrating from Zitadel Quickstart

If you deployed openZro using the previous quickstart script with Zitadel:

Option A - Keep using Zitadel standalone: Continue with your existing setup. No changes needed.

Option B - Add Zitadel as external IdP directly in openZro Management Dashboard:

  1. Deploy new openZro version with embedded IdP
  2. Add your existing Zitadel as an external IdP directly in the openZro Management Dashboard (follow Management Setup above)
  3. Users can continue logging in with Zitadel
  4. Optionally create local user accounts as fallback

Option C - Migrate fully to embedded IdP:

  1. Export user list from Zitadel
  2. Deploy new openZro version with embedded IdP
  3. Recreate users in openZro Dashboard
  4. Decommission Zitadel when ready

Troubleshooting

"Token validation failed" error

  • Verify the issuer URL is correct
  • Ensure User Info inside ID Token is enabled
  • Check that the audience matches your client ID

Service user authentication fails

  • Verify the client secret was copied correctly
  • Ensure the service user has Org User Manager role

Device auth not working

  • Ensure Device Code grant type is enabled
  • Verify PKCE is configured for the application