> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://docs.prividium.com/api/mcp` to find what you need.
>
> **Have feedback?** Use `submit_feedback` on the same MCP server.

This guide provides instructions for integrating an OIDC provider with Prividium™ and configuring initial admin users.

> ### Scope of This Guide
>
> This guide covers how to **connect your existing OIDC provider to Prividium**. It does not cover how to set up,
> secure, or administer your OIDC provider.
>
> **You are responsible for:**
>
> * Creating and securing your OAuth application in your provider
> * Managing users, access policies, and secrets within your provider
> * Ensuring your provider meets your organization's security requirements
>
> Matter Labs is not liable for security issues arising from your OIDC provider configuration. For provider-specific
> setup guidance, refer to your provider's official documentation:
>
> * [Okta Developer Docs](https://developer.okta.com)
> * [Auth0 Docs](https://auth0.com/docs)
> * [Keycloak Documentation](https://www.keycloak.org/documentation)

> **Note:** These instructions use **Okta** as an example. Any OIDC-compliant provider (Auth0, Keycloak, Google, etc.)
> will work — field names may differ slightly by provider. See [Provider-Specific Notes](#provider-specific-notes) if
> you are not using Okta.
>
> **Client Secret not required.** Prividium uses PKCE (public client flow) and does not need a client secret to be
> configured or shared with the deployment team.

## Prerequisites

* OIDC instance deployed and accessible
* Admin access to the OIDC Provider
* Prividium™ deployment infrastructure ready

## Example Deployment

This guide uses Keycloak as the OIDC provider (other providers might differ slightly) and **demo-prividium.zksync.dev**
as the example deployment with the following endpoints:

* **Admin Panel**: https://admin.demo-prividium.zksync.dev/
* **User Panel**: https://user-panel.demo-prividium.zksync.dev/
* **Block Explorer**: https://explorer.demo-prividium.zksync.dev/
* **Prividium API**: https://api.demo-prividium.zksync.dev
* **Block Explorer API**: https://block-explorer-api.demo-prividium.zksync.dev

Replace `demo-prividium.zksync.dev` with your actual deployment domain throughout this guide.

***

## 1. OIDC Administrator Setup (Keycloak)

### 1.1 Create Realm

1. Log into OIDC (Keycloak) Admin Console
2. Create a new realm (or use existing):
   * **Realm Name**: `prividium` (or your organization's preferred name)
   * **Enabled**: `true`
   * **SSL Required**: `external` (or `none` for non-production)
   * **Login with Email Allowed**: `true`

### 1.2 Create OAuth Client

Navigate to **Clients** → **Create Client**:

| Setting                             | Value                 | Description                                |
| ----------------------------------- | --------------------- | ------------------------------------------ |
| **Client ID**                       | `prividium-client`    | Unique identifier for the OAuth client     |
| **Name**                            | `Prividium`           | Display name                               |
| **Protocol**                        | `openid-connect`      | OIDC protocol                              |
| **Client Authentication**           | `Off` (Public client) | Enables PKCE for public clients            |
| **Standard Flow**                   | `Enabled`             | Authorization code flow                    |
| **Direct Access Grants**            | `Enabled`             | Resource owner password credentials        |
| **Valid Redirect URIs**             | See below             | Allowed callback URLs after authentication |
| **Valid Post Logout Redirect URIs** | See below             | Allowed URLs after logout                  |
| **Web Origins**                     | See below             | CORS allowed origins                       |

> **Client Authentication must be Off (public client).** Prividium uses PKCE — no client secret is needed or used.

**Valid Redirect URIs** (for demo-prividium.zksync.dev deployment):

```
https://user-panel.demo-prividium.zksync.dev/*
https://admin.demo-prividium.zksync.dev/*
https://explorer.demo-prividium.zksync.dev/*
```

**Valid Post Logout Redirect URIs**:

```
https://user-panel.demo-prividium.zksync.dev/login
https://admin.demo-prividium.zksync.dev/login
https://explorer.demo-prividium.zksync.dev/
```

**Web Origins** (explicit CORS configuration):

```
https://user-panel.demo-prividium.zksync.dev
https://admin.demo-prividium.zksync.dev
https://explorer.demo-prividium.zksync.dev
```

> **Note**: While `+` (wildcard) can be used for Web Origins to allow all Valid Redirect URIs, explicitly listing each
> origin provides better security and clarity.

### 1.3 Configure Client Settings

In the client's **Advanced** tab:

| Setting                        | Value                   |
| ------------------------------ | ----------------------- |
| **Access Token Lifespan**      | `3600` seconds (1 hour) |
| **PKCE Code Challenge Method** | `S256`                  |

### 1.4 Configure Protocol Mappers

The client needs two protocol mappers to include user information in JWTs:

**Mapper 1: Email**

* Navigate to **Clients** → `prividium-client` → **Client Scopes** → `prividium-client-dedicated` → **Add Mapper** →
  **By Configuration** → **User Property**

| Setting                 | Value    |
| ----------------------- | -------- |
| **Name**                | `email`  |
| **Property**            | `email`  |
| **Token Claim Name**    | `email`  |
| **Claim JSON Type**     | `String` |
| **Add to ID token**     | `On`     |
| **Add to access token** | `On`     |
| **Add to userinfo**     | `On`     |

**Mapper 2: Preferred Username**

* Add another mapper with:

| Setting                 | Value                |
| ----------------------- | -------------------- |
| **Name**                | `preferred_username` |
| **Property**            | `username`           |
| **Token Claim Name**    | `preferred_username` |
| **Claim JSON Type**     | `String`             |
| **Add to ID token**     | `On`                 |
| **Add to access token** | `On`                 |
| **Add to userinfo**     | `On`                 |

### 1.5 Obtain Admin User `sub` ID

For each user who should have admin access in Prividium™:

1. Navigate to **Users** in Keycloak admin console
2. Search for and select the user
3. Copy the **ID** field value (this is the UUID used as the `sub` claim in JWTs)
   * Example UUID: `a1b2c3d4-e5f6-7890-abcd-ef1234567890`

**Provide these IDs to the Prividium™ deployment team** for configuration.

***

## 2. Prividium™ Environment Configuration

### 2.1 Permissions API Configuration

The Permissions API validates JWTs from the OIDC provider and manages user authentication.

| Variable          | Example Value                                                                                                                     | Required | Description                                                                                                   |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `AUTH_METHODS`    | `oidc,crypto_native`                                                                                                              | ✅ Yes   | Must include `oidc` to enable OIDC/JWT validation                                                             |
| `OIDC_JWKS_URI`   | `https://auth.customer.com/realms/prividium/protocol/openid-connect/certs`                                                        | ✅ Yes   | JWKS endpoint for validating JWT signatures from your OIDC provider (Keycloak in this case)                   |
| `OIDC_JWT_ISSUER` | `https://auth.customer.com/realms/prividium`                                                                                      | ✅ Yes   | Expected `iss` (issuer) claim in JWTs - must exactly match your OIDC provider's issuer                        |
| `OIDC_JWT_AUD`    | `prividium-client`                                                                                                                | ✅ Yes   | Expected `aud` (audience) claim in JWTs - must match the client ID in your OIDC provider                      |
| `OIDC_ADMIN_SUBS` | `a1b2c3d4-e5f6-7890-abcd-ef1234567890,b2c3d4e5-f6a7-8901-bcde-f12345678901`                                                       | ✅ Yes   | Comma-separated list of user `sub` IDs (from your OIDC provider) that should receive admin role automatically |
| `CORS_ORIGIN`     | `https://admin.demo-prividium.zksync.dev,https://user-panel.demo-prividium.zksync.dev,https://explorer.demo-prividium.zksync.dev` | ✅ Yes   | Comma-separated list of allowed CORS origins for API requests                                                 |

**Important Notes:**

* Replace `auth.customer.com` with your actual OIDC domain
* Replace `prividium` in the URLs if you used a different realm name
* The JWKS URI, issuer, and audience must match exactly with the OIDC provider's configuration
* `OIDC_ADMIN_SUBS` requires at least one UUID to grant initial admin access
* `CORS_ORIGIN` must include all frontend application URLs that will call the Permissions API

### 2.2 User Panel Configuration

The User Panel frontend handles OIDC authentication flow and user interactions.

| Variable                           | Example Value                                              | Required | Description                                                                   |
| ---------------------------------- | ---------------------------------------------------------- | -------- | ----------------------------------------------------------------------------- |
| `VITE_AUTH_METHODS`                | `oidc,crypto_native`                                       | ✅ Yes   | Must include `oidc`                                                           |
| `VITE_OIDC_AUTHORITY`              | `https://auth.customer.com/realms/prividium`               | ✅ Yes   | Keycloak realm URL - used for OIDC discovery to fetch endpoints automatically |
| `VITE_OIDC_CLIENT_ID`              | `prividium-client`                                         | ✅ Yes   | OAuth client ID from Keycloak - must match the client created in section 1.2  |
| `VITE_OIDC_BUTTON_TEXT`            | `Sign in with Company SSO`                                 | ❌ No    | Custom text displayed on the OIDC login button (default: "Sign in with OIDC") |
| `VITE_ADMIN_PANEL_REDIRECT_URI`    | `https://admin.demo-prividium.zksync.dev/callback`         | ✅ Yes   | OAuth callback URL for Admin Panel OIDC authentication                        |
| `VITE_BLOCK_EXPLORER_REDIRECT_URI` | `https://explorer.demo-prividium.zksync.dev/auth/callback` | ✅ Yes   | OAuth callback URL for Block Explorer OIDC authentication                     |

**Important Notes:**

* All redirect URIs must be registered in your OIDC provider (see section 1.2)
* The authority URL should point to your OIDC provider realm (no trailing slash)
* Each Prividium™ application (User Panel, Admin Panel, Block Explorer) has its own callback URI that must be
  configured

### 2.3 Admin Panel Configuration

The Admin Panel uses the same OIDC configuration as the User Panel. No additional OIDC-specific environment variables
are required - authentication is inherited from the User Panel's OIDC setup.

### 2.4 Per-Organization OIDC Provider (Multi-Org)

When Multi-Org is enabled, each organization can have its own OIDC provider. Configure it via the Admin Panel or the
Permissions API (`PUT /organizations/:id/oidc-provider`).

The **required** `userPanelUrl` field is the organization's own user panel domain (e.g.
`https://user-panel.acme.<your-domain>`). The admin panel sends org-admin logins there, and each organization signs in
only on its own domain — the zone user panel never serves an organization login. It is required so an organization
provider can never be saved in a state where org-admin login silently falls back to the zone panel. The optional
`displayName` controls the login button label — users see **Sign in with \<displayName>** in place of the zone-level
`VITE_OIDC_BUTTON_TEXT` fallback.

Register the organization user panel's `/callback` and `/login` paths, and the org admin panel's `/callback`, in the
organization's identity provider (its redirect URIs and web origins) — scoped to the organization's own domain, not the
zone domain.

***

## 3. Initial Admin User Setup

Prividium™ grants admin privileges automatically to users whose OIDC `sub` ID is listed in the `OIDC_ADMIN_SUBS`
environment variable.

### Steps:

1. **OIDC Administrator**: Obtain the `sub` ID(s) of existing OIDC user(s) who should have Prividium™ admin access (see
   section 1.5)

2. **Deployment Team**: Add the ID(s) to the `OIDC_ADMIN_SUBS` environment variable in the Permissions API configuration
   * Format: Comma-separated list with no spaces
   * Example: `a1b2c3d4-e5f6-7890-abcd-ef1234567890,b2c3d4e5-f6a7-8901-bcde-f12345678901`

3. **Deploy/Restart**: Deploy the Permissions API with the updated configuration

4. **User Login**: The admin user logs into the User Panel via OIDC (Keycloak)

5. **Automatic Role Assignment**: When the user first calls the `/api/profiles/from-jwt` endpoint (happens automatically
   after login), Prividium™:
   * Checks if the user's `sub` claim (UUID) is in `OIDC_ADMIN_SUBS`
   * Automatically grants the admin role if matched
   * Creates the user record in Prividium's database if it doesn't exist

### How to Find User `sub` ID

**Method 1: Keycloak Admin UI**

1. Log into Keycloak Admin Console
2. Navigate to **Users**
3. Search for and select the user
4. Copy the **ID** field (e.g., `a1b2c3d4-e5f6-7890-abcd-ef1234567890`)

**Method 2: Decode JWT Token**

1. Have the user log into the User Panel
2. Capture the JWT access token (from browser DevTools → Application → Local Storage)
3. Decode `oidc_auth_token` at [jwt.io](https://jwt.io)
4. Copy the `sub` claim value

***

## Provider-Specific Notes

### Auth0

When using Auth0, the application dashboard uses different field names from Keycloak. Use this mapping:

| Purpose                                                             | Auth0 Field Name          |
| ------------------------------------------------------------------- | ------------------------- |
| Redirect URI (`https://<user-panel-domain>/callback` etc.)          | **Allowed Callback URLs** |
| Post-logout Redirect URI (`https://<user-panel-domain>/login` etc.) | **Allowed Logout URLs**   |

> **Do not use "Application Login URI"** for the callback URL — this field serves a different purpose and will not
> resolve the OAuth redirect.

**Required URL registrations** for a deployment at `<your-domain>`:

* **Allowed Callback URLs**: `https://user-panel.<your-domain>/callback` (Admin Panel and Block Explorer flows go
  through the User Panel callback — no additional entries needed)
* **Allowed Logout URLs**: `https://user-panel.<your-domain>/login` (Only the User Panel logout URL is required)

**Application Authentication setting:**

Set **Application Authentication** to **None**. This disables client secret authentication and enables the PKCE public
client flow, which Prividium requires. Do not configure a client secret.

**Finding the user `sub` ID in Auth0:**

1. Navigate to **User Management** → **Users**
2. Select the user
3. Copy the **User ID** field exactly as shown — the format depends on the login provider:
   * `auth0|xxxxxxxxxxxxxxxxxxxxxxxx` (Auth0 native users)
   * `google-oauth2|117785210703185091993` (Google login)
4. Use the full string including the prefix when setting `OIDC_ADMIN_SUBS`

**Auth0 environment variable values:**

| Variable          | Value                                                                                      |
| ----------------- | ------------------------------------------------------------------------------------------ |
| `OIDC_JWKS_URI`   | `https://<your-auth0-domain>/.well-known/jwks.json`                                        |
| `OIDC_JWT_ISSUER` | `https://<your-auth0-domain>/` (Auth0 includes a trailing slash — this must match exactly) |
| `OIDC_JWT_AUD`    | Your Auth0 application's **Client ID**                                                     |

***

## Complete Configuration Example

For a deployment at **demo-prividium.zksync.dev** with Keycloak at **auth.customer.com**:

### Keycloak Client Configuration

* **Client ID**: `prividium-client`
* **Valid Redirect URIs**:
  * `https://user-panel.demo-prividium.zksync.dev/*`
  * `https://admin.demo-prividium.zksync.dev/*`
  * `https://explorer.demo-prividium.zksync.dev/*`
* **Web Origins**:
  * `https://user-panel.demo-prividium.zksync.dev`
  * `https://admin.demo-prividium.zksync.dev`
  * `https://explorer.demo-prividium.zksync.dev`

### Permissions API Environment Variables

```bash
AUTH_METHODS=oidc,crypto_native
OIDC_JWKS_URI=https://auth.customer.com/realms/prividium/protocol/openid-connect/certs
OIDC_JWT_ISSUER=https://auth.customer.com/realms/prividium
OIDC_JWT_AUD=prividium-client
OIDC_ADMIN_SUBS=a1b2c3d4-e5f6-7890-abcd-ef1234567890
CORS_ORIGIN=https://admin.demo-prividium.zksync.dev,https://user-panel.demo-prividium.zksync.dev,https://explorer.demo-prividium.zksync.dev
```

### User Panel Environment Variables

```bash
VITE_AUTH_METHODS=oidc,crypto_native
VITE_OIDC_AUTHORITY=https://auth.customer.com/realms/prividium
VITE_OIDC_CLIENT_ID=prividium-client
VITE_OIDC_BUTTON_TEXT=Sign in with Company SSO
VITE_ADMIN_PANEL_REDIRECT_URI=https://admin.demo-prividium.zksync.dev/callback
VITE_BLOCK_EXPLORER_REDIRECT_URI=https://explorer.demo-prividium.zksync.dev/auth/callback
```
