VAM signs users in with OpenID Connect (OIDC). You choose the provider during installation (the Identity provider step of the wizard, see Running the installer). Two broad options exist:
- Bundled Keycloak: the installer deploys and configures a Keycloak instance for you. It is not an officially supported deployment option, but it is fully pre-configured and is expected to work out of the box, which makes it the easiest way to get going. Nothing in this guide is required; skip straight to Signing in.
- External OIDC: you point VAM at an identity provider you already run: Microsoft Entra ID (Azure AD), Okta, Auth0, or your own Keycloak. This requires some one-time setup in your provider before you run the installer.
Two different “Microsoft” integrations — don't confuse them. This page is about sign-in (Entra ID / OIDC). If instead you are looking for how VAM obtains its TLS certificate from Microsoft AD Certificate Services (AD CS), that is the certificate step, not identity — see Existing / native Kubernetes → Certificates and the TLS certificate options.
This guide walks through that one-time setup. Most of it is written for Microsoft Entra ID, because Entra needs the most explicit configuration; the other providers section at the end covers the differences for Okta, Auth0 and external Keycloak.
Do this before you run the installer. The installer's Identity provider step asks for the IDs and secret you create here. Having them ready makes the install a single pass.
How VAM Uses Your Identity Provider
VAM is more than a single web app, so understanding what it asks of your provider helps the setup make sense:
VAM component | What it does with the token |
|---|---|
Configuration UI | Interactive browser sign-in (authorization-code + PKCE). The user's token is the entry point. |
VAM API / services | Validate the inbound user token, then act as that user for every downstream call. |
Object storage (MinIO/S3) | Exchanges the user token for short-lived, user-scoped storage credentials (STS |
Message broker (RabbitMQ) | Validates the same token for management/messaging access. |
Background work | Re-mints a correctly-audienced token on behalf of the original user (Entra On-Behalf-Of). |
Two consequences fall out of this and drive the whole setup:
- Roles travel in the token. VAM authorizes users from a role claim. The same role values are also what object storage maps to storage policies. Get the roles right and everything downstream works; get them wrong and the user signs in but can do nothing.
- VAM must be able to act on behalf of the user. On Entra, access tokens are audience-locked — a token minted for the UI is not automatically valid for the API or for storage. VAM therefore needs to be a confidential client with a certificate credential so it can perform the On-Behalf-Of exchange. The installer provisions that certificate; you only need to allow the flow.
Microsoft Entra ID
Create one app registration that backs every VAM client (the UI, the API, the broker and the storage callback all use the same application). The steps are:
- Register the application
- Expose an API and add scopes
- Add API permissions and grant consent
- Define app roles
- Add a client secret
- Force v2 access tokens
- Assign users and groups to roles
- Collect the values for the installer
You need an Entra account with permission to create app registrations and grant admin consent (an Application Administrator or Cloud Application Administrator, or a Global Administrator).
Throughout, replace <vam-host> with the public hostname you will give VAM (for example vam.example.com).
1. Register the Application
-
In the Entra admin center, go to Identity → Applications → App registrations → New registration.
-
Name:
VAM(or any name you recognize). -
Supported account types: Accounts in this organizational directory only (single tenant) unless you have a specific multi-tenant requirement.
-
Redirect URI: select Single-page application (SPA) and enter the Configuration UI callback:
https://<vam-host>/config/auth/callback -
Click Register.
After registration, open Authentication and add the remaining redirect URIs VAM uses. Add each under the platform shown:
Platform | Redirect URI | Used by |
|---|---|---|
Single-page application |
| Configuration UI |
Single-page application |
| VAM web apps |
Single-page application |
| Viz Pilot Edge SPA |
Single-page application |
| Template Builder SPA |
Single-page application |
| Data Server Config SPA |
Web |
| Object-storage console |
Web |
| Message-broker console |
The exact ports for the storage and broker consoles depend on your ingress configuration. The values above are the defaults; if you changed them, adjust accordingly. You can also add these later — they are only needed for the respective admin consoles, not for normal VAM use.
The three Pilot Edge SPA redirect URIs are only required if you deploy Viz Pilot Edge / Template Builder / Data Server Config. Entra does not accept
*wildcards in SPA redirect URIs — register the concrete callback for each SPA (the SPA's served path, for example, >https://<vam-host>/pilot/). See Pilot Core Service and Pilot Edge.
From the Overview page record the Application (client) ID and the Directory (tenant) ID — you need both for the installer.
2. Expose an API
VAM validates tokens against its own Application ID URI, so the application has to expose one.
- Open Expose an API.
- Next to Application ID URI, click Add and accept the default
api://<client-id>. - Add a scope named
management-uiif you want browser sign-in to the message-broker management console. No other scope is required.
The installer requests the
<client-id>/.defaultscope, which aggregates all scopes and app permissions you have granted. You do not have to wire each scope into the installer individually — just make sure they exist and are consented (next step).
3. API Permissions
- Open API permissions.
- Confirm the Microsoft Graph → Delegated permissions include:
openid,profile,email,offline_accessandUser.Read. Add any that are missing (Add a permission → Microsoft Graph → Delegated permissions). - Click Grant admin consent for <your tenant>. Every permission row must show a green Granted state.
If you skip admin consent, each user is prompted to consent individually — and for app permissions that require admin consent they are simply blocked. Always grant admin consent here.
4. Define App Roles
Roles are how VAM authorizes users. The value of each role is what appears in the token's roles claim, and VAM (and object storage) match on that value — so the values below must be exact.
-
Open App roles → Create app role.
-
Create at least the roles your deployment needs:
Display name
Value
Allowed member types
Purpose
VAM Service access
vamUsers/Groups
Required. Grants access to the VAM API. Without it, sign-in succeeds but every API call is rejected.
Storage read/write
readwriteUsers/Groups
Read/write access to object storage (maps to the storage
readwritepolicy).Storage admin
consoleAdminUsers/Groups
Full object-storage administration (maps to the storage
consoleAdminpolicy).Configuration admin
vam-adminUsers/Groups
Access to the Configuration Service. The Configuration Service requires this exact role on every endpoint — there is no separate read-only tier.
Set every role's state to Enabled.
If you deploy Viz Pilot Edge / Pilot Core Service, add these roles as well (their values must be exact — Pilot Core Service authorizes on them directly):
Display name
Value
Allowed member types
Purpose
Pilot administrator
pilot-adminUsers/Groups
Full Pilot Edge administration (PCS Admin, Template Builder, Data Server settings).
Pilot editor
pilot-editorUsers/Groups
Create and edit Pilot data elements and templates.
Pilot journalist
pilot-journalistUsers/Groups
Edit Pilot data elements (journalist workflow).
Graphic designer
graphic-designerUsers/Groups
Template Builder / graphics authoring.
Pilot MSE (read)
pilot-mseApplications
Read-only access for the Media Sequencer Engine and other Vizrt services.
See Pilot Core Service and Pilot Edge for how these roles map to Pilot's authorization policies and for the collection-scoped role convention.
The
vamrole is mandatory. It is the gate the VAM API checks on every request. The storage role values (readwrite,consoleAdmin) must match the names of the object-storage policies they map to (see Object storage trust). The Pilot role values (pilot-admin,pilot-editor,pilot-journalist,graphic-designer,pilot-mse) must match exactly — Pilot Core Service checks them by name.
5. Client Secret
VAM uses a certificate for the On-Behalf-Of exchange (the installer provisions it), but a client secret is still required for the standard confidential-client configuration.
- Open Certificates & secrets → Client secrets → New client secret.
- Give it a description (
VAM) and an expiry that matches your rotation policy. - Click Add and copy the secret value immediately — Entra shows it only once. This is the value you enter as the OIDC client secret in the installer.
Set a calendar reminder before the secret expires. When it lapses, sign-in and token exchange break until you create a new secret and update VAM's Platform → Identity settings.
6. Force v2 Access Tokens
VAM expects v2.0 access tokens (the roles claim and the v2.0 issuer depend on it).
-
Open Manifest.
-
Find
requestedAccessTokenVersionand set it to2:"requestedAccessTokenVersion":2 -
Save.
7. Assign Users
Because the app exposes app roles, Entra by default only lets assigned users sign in and only assigned users receive role claims.
- From the app registration's Overview, click the linked Managed application (this opens the matching Enterprise application).
- Open Users and groups → Add user/group.
- Select the users or groups and assign the appropriate role (
vamplus whatever storage/config roles they need).
Assign roles to groups rather than individual users where you can — it is far easier to manage at scale. A user with no role assignment can authenticate but has no access.
8. Values for the Installer
When you reach the installer's Identity provider step, choose External OIDC, select Microsoft Entra ID as the provider and enter:
Installer field | Value |
|---|---|
Provider |
|
Host |
|
Tenant / App ID | your Directory (tenant) ID (from step 1) |
Client ID | your Application (client) ID (from step 1) |
Client secret | the secret value from step 5 |
From these the installer derives the values VAM actually uses:
Derived value | Form |
|---|---|
Authority |
|
Token endpoint |
|
Discovery URL |
|
Requested scope |
|
Role claim |
|
You do not type these in — they are listed so you can verify them in Platform → Identity after install, or in a support case.
Object Storage Trust
VAM's object storage (MinIO / S3) issues each user short-lived, user-scoped credentials by validating the user's token directly (STS AssumeRoleWithWebIdentity). For that to work, the storage layer must:
-
Trust your Entra issuer. The installer configures the storage OIDC settings to the same authority and client ID you entered above. No manual step is required for a standard install.
-
Map the role claim to a storage policy. Storage reads the
rolesclaim and looks for a policy of the same name. This is why the app-role values in step 4 must match storage policy names:Role value
Storage policy
Effect
readwritereadwriteRead and write objects.
consoleAdminconsoleAdminFull storage administration.
If a user can sign in to VAM but uploads or downloads fail with an access denied error from storage, the cause is almost always a missing or mis-named storage role — check that the user carries a role value matching a storage policy. See Troubleshooting → Sign-in and authorization.
Pilot Core Service and Pilot Edge
If your deployment includes Viz Pilot Edge and the Pilot Core Service (PCS), there is some extra identity-provider setup on top of the base VAM configuration above. Skip this section entirely if you do not deploy Pilot.
Pilot has three moving parts that touch the identity provider:
Part | Sign-in style |
|---|---|
Pilot Edge browser SPAs | Three single-page apps — Pilot, Template Builder, Data Server Config — sign in with authorization-code + PKCE. |
Pilot Core Service (PCS) | Validates the user's access token on every API call: checks the audience, then authorizes on Pilot roles. |
Media Sequencer / services | Other Vizrt services call PCS read-only with a service token carrying the |
1. Register (or Reuse) Redirect URIs for the Three SPAs
The three Pilot SPAs are served under /pilot/, /template-builder/ and /data-server-config/. Their callbacks are the redirect URIs you already added in step 1:
https://<vam-host>/pilot/https://<vam-host>/template-builder/https://<vam-host>/data-server-config/On Entra, register each as a concrete SPA redirect URI (the served path of the app). Entra rejects
*wildcards for SPA platform URIs — the/pilot/*form shown in the bundled-Keycloak realm only works for Keycloak. PCS's ownsso.jsonmaps all three SPAs to a single client ID, so they can share the VAM app registration (or you can give Pilot its own registration; either way the redirect URIs above must be present).
2. Define the Pilot Roles
PCS authorizes every request against the roles claim, by exact role-value match. Add the five Pilot roles from step 4 (pilot-admin, pilot-editor, pilot-journalist, graphic-designer, pilot-mse). They map to PCS's authorization policies like this:
PCS policy | Satisfied by role(s) | Used for |
|---|---|---|
Pilot admin |
| PCS Admin, Template Builder, Data Server settings. |
Graphic designer |
| Template / graphics authoring. |
Pilot journalist |
| Create / edit Pilot data elements. |
Pilot read-only |
| Read endpoints used by MSE and other Vizrt services. |
The roles are additive in capability:
pilot-adminsatisfies every policy,pilot-mseonly the read-only one. Assignpilot-mseto the service principal (MSE / integrations), not to people.
3. Make Sure PCS Receives a Usable Audience
PCS rejects a token unless it validates the issuer and the audience (aud). Two consequences:
- Bundled Keycloak: handled for you. The realm's
audienceclient scope stamps theviz-amaudience onto user tokens, and the installer sets PCS's expected audience to match. - Entra (or other external OIDC): the access token the SPA obtains must carry an audience PCS is configured to accept. In practice this means requesting the Pilot/PCS API scope so Entra issues a token audienced for it. The installer records this as PCS's
SSO:Audience; the SPAs request it through an extra scope of the form<pcs-api>/.default(for exampleVizPilot/.default).
If PCS returns 401 Unauthorized for a user who can sign in to the rest of VAM, the token almost always has the wrong audience — the SPA obtained a token audienced for the UI, not for PCS. Check that the Pilot/PCS scope is being requested and that PCS's
SSO:Audiencematches theaudin the issued token.
4. Collection-Scoped Roles (Optional, Advanced)
Beyond the five flat roles, PCS supports per-collection access: any role whose value begins with the prefix pilot-collection (for example pilot-collection-sports) grants the user access to the matching Pilot collection. This is opt-in — define such roles only if you use Pilot collection-level segregation, and make the suffix match your collection names. The prefix itself is configurable (SSO:PilotCollectionPrefix, default pilot-collection).
Other Providers
Everything above is written for Microsoft Entra ID. VAM also supports three other provider families. Before you invest time configuring one, check how complete that support is:
Provider | Interactive sign-in | Object-storage (MinIO) | Background / delegated work (token re-mint) | Support status |
|---|---|---|---|---|
Bundled Keycloak | ✅ | ✅ | ✅ (RFC 8693, pre-configured) | Not officially supported — but pre-configured and expected to work |
Microsoft Entra ID | ✅ | ✅ | ✅ (On-Behalf-Of, certificate) | Supported |
External Keycloak | ✅ | ✅ | ✅ if token exchange is enabled in your realm | Supported |
Okta | ✅ | ✅ (group claim) | ⚠️ Limited — see notes | Preview |
Auth0 | ✅ | ⚠️ Needs a custom claim | ❌ No standard token exchange | Preview |
What "Preview" means. Interactive sign-in to the Configuration UI works for every provider in the list. The caveats are about the two things VAM does after sign-in: mapping the role/group claim to object-storage policies, and re-minting a token for background work (transcode, import, async indexing). For Okta and Auth0 those paths are not yet validated end-to-end — read the per-provider notes before committing to them for production.
The runtime only distinguishes Entra from everything else: a non-Microsoft issuer is treated as a Keycloak-style provider, and the delegated token re-mint uses the Keycloak RFC 8693 token-exchange call. That is why external Keycloak is fully supported, while Okta and Auth0 (which do not implement RFC 8693 the same way) fall back to running the user's original token and degrade to the service identity for background jobs.
Local Keycloak for Development (Not Officially Supported)
If you are a developer running VAM locally (outside the installer), you can point it at a standalone Keycloak you run yourself — for example a quay.io/keycloak/keycloak container started in dev mode. This is a development-only convenience and is not an officially supported deployment option: for any real install, use the bundled Keycloak the installer provisions, which is configured correctly out of the box.
To stand one up for local development:
- Run Keycloak in dev mode and create a realm named
vam. - Import the realm shape VAM expects (see the bundled realm below) — the clients
viz-am,swagger,rabbitmq,vue-config-web-appandpilot-edge, thepolicyclaim mapper and the audience mappers. The simplest path is to export the bundled realm from a throwaway installer run and import it into your local Keycloak. - Point VAM's
OidcHostat the realm URL (http://localhost:8080/realms/vam).
Because none of the installer's TLS, CA-trust or ingress wiring applies here, you are responsible for making the realm reachable from every VAM component. Treat broken background/STS flows in this setup as expected, not as bugs.
External Keycloak
Use this when you already run your own Keycloak and want VAM to use it instead of the bundled instance. VAM treats it exactly like the bundled Keycloak — same fixed client IDs, same claim — so your realm must mirror the bundled realm's shape. This is the most involved part: the installer does not let you rename these clients.
-
Create a realm (any name; you will give VAM its full realm URL).
-
Create the clients VAM expects, with these exact client IDs:
Client ID
Type
Used by
viz-amConfidential (client secret)
VAM API / services (also OBO/exchange)
vue-config-web-appPublic (PKCE)
Configuration UI browser sign-in
swaggerPublic (PKCE)
API explorer
rabbitmqConfidential
Message broker validation
pilot-edgePublic (PKCE)
Pilot Edge / Template Builder / Data Server Config (only if you use Pilot)
-
Redirect URIs: add the same callback URLs listed in section 1 (config UI, MinIO console, Swagger and the Pilot paths if applicable) to the matching clients.
-
Realm roles: create the VAM roles and storage policies as realm roles:
vam(mandatory API gate), your storage policy names (for example,readwrite,consoleAdmin) and the Pilot roles (pilot-admin,pilot-editor,pilot-journalist,graphic-designer) if you use Pilot. See section 4 for what each role does. -
Claim mapper: add a realm-roles mapper that emits the roles into a claim named
policy(token claim namepolicy, multivalued, added to the access token). VAM and MinIO both readpolicy. -
Audience mappers: stamp the
viz-amandrabbitmqaudiences onto issued tokens so the API and broker accept them. -
Enable token exchange on the
viz-amclient if you want background/delegated work to act as the original user (VAM uses RFC 8693). Without it, async jobs fall back to the service identity. -
Installer values: set Provider =
Keycloak, Host = the full realm URL (for example,https://keycloak.example.com/realms/vam) and theviz-amclient secret. The other client IDs are fixed, so there is nothing else to enter.
Private CA. The installer only mounts its CA trust bundle for the bundled Keycloak. If your external Keycloak presents a certificate from a private CA, VAM components must already trust that CA at the OS level, or TLS to the realm's discovery and token endpoints fails.
Okta
Okta works as a standard-discovery provider: the host you enter is the issuer/authority verbatim, the token endpoint is <host>/v1/token and the group claim (groups) carries authorization. Unlike Keycloak, one Okta app's client ID is reused for every VAM client and audience.
- Create an OIDC application of type Web (it needs a client secret for the confidential flows).
- Sign-in redirect URIs: add the VAM callback URLs from section 1 (config UI, MinIO console, Swagger).
- Groups: create groups whose names exactly match the VAM roles and storage policies you need:
vam(mandatory), your storage-policy names (for example,readwrite,consoleAdmin) and any Pilot roles. Assign users to the groups. - Groups claim: in the app's OpenID Connect ID Token / access token settings (or your custom authorization server's claims), add a claim named
groupsthat includes the groups and make sure it is emitted on the access token (not only the ID token), because VAM and MinIO authorize from the access token. - Installer values: Provider =
Okta, Host = your Okta issuer (your org URL, orhttps://<org>.okta.com/oauth2/<authServerId>if you use a custom authorization server), plus the app's client ID and client secret. Enter the same client ID for the shared/SPA client ID field.
Preview caveats. The access-token audience VAM validates is the app's own client ID, and the request scopes are the standard OIDC set (
openid profile email offline_access) — there is no resource scope for the broker, so RabbitMQ OAuth may need tuning. Background/delegated re-mint uses RFC 8693requested_subject, which Okta's token-exchange grant does not support, so async jobs run as the service identity.
Auth0
Auth0 is also a standard-discovery provider: token endpoint <host>/oauth/token, discovery at <host>/.well-known/openid-configuration.
- Create a Regular Web Application (confidential, has a client secret).
- Allowed Callback URLs: add the VAM callback URLs from section 1.
- Roles / authorization: model your VAM roles (
vam, storage policies, Pilot roles) however you prefer (Auth0 Roles, app metadata, or a database), then add them to the token with an Action. - Claim: VAM reads the policy/role claim named
policy. Auth0 strips non-namespaced custom claims from tokens, so an Action that simply addspolicymay not survive. This is the main limitation (see below). - Installer values: Provider =
Auth0, Host = your tenant domain (https://<tenant>.auth0.com), plus the application's client ID and client secret.
Preview caveats — read before choosing Auth0. Two gaps currently make Auth0 unsuitable for production: (1) VAM expects the role claim to be named exactly
policy, but Auth0 only reliably emits namespaced custom claims, so object-storage policy mapping may not resolve; and (2) Auth0 does not implement RFC 8693 token exchange, so VAM cannot re-mint a delegated token for background work — those jobs run as the service identity. Interactive sign-in works, but treat Auth0 as a preview integration only.
Changing the Provider After Install
You can change identity-provider settings later in the Configuration Service under Platform → Identity — for example to rotate the client secret or point at a different tenant. Sign-in is briefly interrupted while the change rolls out. If you switch provider family (say Keycloak → Entra), re-create the role assignments in the new provider first so users are not locked out.