Skip to content

Reference

alter identity-providers

Stand up an end-user identity provider (OIDC) for an app from the CLI.

An app can trust an external identity provider (Auth0, Clerk, Okta, WorkOS) so its end users sign in with their existing accounts. These commands stand one up.

Identity providers are included on every plan.

alter identity-providers discover --issuer-url <url>
alter identity-providers create --issuer-url <url> (--audience ... | --wallet-client-id ... --wallet-client-secret ...)
alter identity-providers webhook enable --provider <id> [--secret -|@file|<value>]
alter identity-providers webhook disable --provider <id> [--yes] [--force --confirm <issuer-host>]
alter identity-providers webhook rotate --provider <id> [--secret -|@file|<value>] [--yes]
alter identity-providers webhook status --provider <id>

App-scoped commands take --app <id> (or the app’s name), or link a workspace / set ALTER_APP_ID. discover / create need dashboard_identity_providers:create; the webhook subcommands need dashboard_identity_providers:webhooks. Because identity-provider configuration is an organization-admin action, only an organization admin can mint a token carrying these scopes — alter auth login --scopes dashboard_identity_providers:create (or …:webhooks) run by a non-admin is refused at sign-in. Both grants are literal-only: * and dashboard_identity_providers:* do not cover them. The namespace is also available as alter idp, and create accepts the alias configure.

Preview OIDC discovery for an issuer URL without saving anything. Returns the detected provider type, JWKS URI, and suggested claim mappings, so the mappings can be verified — or overridden on create — before the one-shot create.

FlagRequiredDescription
--issuer-url <url>yesOIDC issuer URL (e.g. https://acme.okta.com). The issuer itself, not a /.well-known/... URL. A bare host with no scheme (e.g. WorkOS’s acme-corp.authkit.app) is accepted — https:// is prepended. The normalized URL must be HTTPS and at most 512 characters; localhost and explicit HTTP are rejected locally.
Terminal window
alter identity-providers discover --issuer-url https://acme.okta.com

--user-id-claim sub names the field containing a user ID; do not pass an actual user ID or email. --audience takes the exact audience value registered with the provider, not the word aud. --wallet-client-id takes the OIDC application’s Client ID. For sign-in only, supply the wallet client pair and omit --audience. See Choose the right values for provider-specific creation steps, including WorkOS’s two different client IDs.

Finalize claims and accepted audiences before the first successful token resolution locks them, even through token-only verification. A successful create does not verify callbacks, user assignment, MFA, emitted claims, webhook delivery, or a full directory import. Follow the verification and recovery checklist.

Configure the identity provider for the app. Discovery runs against the issuer and must succeed — an unreachable or invalid issuer is rejected and nothing is saved. Claim mappings are auto-detected from the issuer; pass the override flags to set them explicitly. Every create needs an effective audience, supplied either explicitly with --audience or implicitly by the wallet client pair.

FlagRequiredDescription
--issuer-url <url>yes (unless --input)OIDC issuer URL (e.g. https://acme.okta.com). The issuer itself, not a /.well-known/... URL. A bare host with no scheme (e.g. WorkOS’s acme-corp.authkit.app) is accepted — https:// is prepended. The normalized URL must be HTTPS and at most 512 characters; localhost and explicit HTTP are rejected locally.
--audience <aud>conditionalExpected JWT aud claim (maximum 512 characters). Required unless --wallet-client-id supplies the OIDC relying-party audience. Tokens without the effective audience are rejected.
--user-id-claim <claim>noOverride the user-identity claim (auto-detected; defaults to sub; maximum 128 characters).
--group-claim <claim>noOverride the group-membership claim (auto-detected; maximum 128 characters).
--group-claim-is-idnoAssert the group claim emits stable group IDs (Okta 00g…, WorkOS org_…) rather than display names. Required for Okta/WorkOS group-principal grants; cannot be changed after the first user signs in. Requires --group-claim. (Auth0 group grants are not currently supported.)
--role-claim <claim>noOverride the role claim (auto-detected; maximum 128 characters).
--wallet-client-id <id>noOIDC client ID for interactive wallet sign-in and Connect delegation approval (maximum 255 characters). Must be paired with --wallet-client-secret. Without the pair, the response’s connect_delegation_signin_configured is false: users cannot approve managed-secret delegations, and OAuth delegations skip the already-connected shortcut.
--wallet-client-secret <value>noOIDC client secret for wallet sign-in. Use - to read from stdin or @/path/to/file; an inline value prints a shell-history warning. Must be paired with --wallet-client-id.
--input <path>noJSON body from a file (@path) or stdin (-); replaces the per-field flags. Field names are the wire names (issuer_url, group_claim, group_claim_is_id, …). The CLI applies the same issuer, audience, field-length, wallet-pair, and group-claim checks as the flag form before sending the request.

Without the wallet flags, the identity provider validates inbound tokens and --audience is required. To also enable interactive wallet sign-in, pass both wallet flags — they are all-or-nothing, the audience defaults to the client ID, and the credentials are verified against the provider before anything is saved. A hard rejection fails the create with nothing saved; if verification is inconclusive (for example a transient network issue), the save proceeds unverified and the CLI prints a notice on stderr — verify with a sign-in.

The wallet pair is also what lets users approve Connect delegations. A user approves a managed-secret delegation to an agent only after signing in through this identity provider on a page Alter runs, so a token-validation-only provider cannot approve any. The create response reports this in the read-only connect_delegation_signin_configured field (with connect_delegation_signin_reason naming what is missing: missing_client_id, missing_client_secret, or issuer_cannot_sign_in). When it is false, every managed-secret delegation request for the app fails with idp_signin_not_configured; OAuth delegations still work, but the user always goes through the provider’s own authorization, because approving on an already-connected account also needs this sign-in. The CLI says so on stderr, with the fix for the reason:

alter: connect_delegation_signin_configured is false (reason: missing_client_id) — users cannot approve managed-secret Connect delegations to agents (those requests fail with idp_signin_not_configured), and OAuth delegations go through the provider's own authorization instead of the already-connected shortcut. To fix: pass --wallet-client-id and --wallet-client-secret (the provider now exists, so add them in the dashboard).
connect_delegation_signin_reasonFix
missing_client_id, missing_client_secretAdd the sign-in client ID and secret. create takes them as --wallet-client-id / --wallet-client-secret; once the provider exists, add them in the dashboard.
issuer_cannot_sign_inThe issuer validates tokens but cannot sign users in. Use an issuer that supports OpenID Connect sign-in — for WorkOS, the AuthKit issuer https://<slug>.authkit.app, not https://api.workos.com/user_management/<client_id>.

The same sign-in uses the SDK callback URL, so register it with the provider as well as the wallet callback URL.

--audience is probed when the provider supports the audience authorize parameter. Auth0 validates it; Clerk does not receive it during sign-in. An unsupported audience can break sign-in at providers that validate the parameter. A rejected audience fails the create with nothing saved and exit code 1 (a validation rejection, per the exit-code table in the scripting guide), and the error names the provider’s own reason. When the audience cannot be checked — the probe did not complete, or no wallet client pair was supplied to check it with — the create succeeds and the CLI prints the verdict on stderr:

alter: audience preflight: skipped — The audience "https://api.example.com" was NOT verified: wallet sign-in credentials are not configured, so there is no client to probe the identity provider with.

A rejection is a non-zero exit, not a stderr notice. Redirect stderr to keep it out of a JSON pipeline; do not discard it, since it is the only place an unverified audience is reported.

Terminal window
alter identity-providers create \
--issuer-url https://acme.okta.com/oauth2/default \
--audience api://default

Manage the identity provider’s webhook integration — how Alter receives events (e.g. group-sync) from the provider. These need the dashboard_identity_providers:webhooks scope, are app-scoped like the rest of the namespace (pass --app <id> (or the app’s name), or use a linked workspace / ALTER_APP_ID), and identify the provider with --provider <id>. Enabling and rotating return the signing secret in the webhook_secret field, shown once; capture it in the same pipeline (--output json | jq -r '.webhook_secret').

FlagRequiredDescription
--app <app-id-or-name>yes*The application (*or link a workspace / set ALTER_APP_ID).
--provider <provider-id>yesThe identity provider’s ID.
--secret <value>noSigning secret for enable / rotate. For Clerk, paste the Dashboard whsec_ value; for Okta, the Event Hook secret; for WorkOS, the endpoint’s signing secret from WorkOS Dashboard → Webhooks (any format — the whsec_ prefix is not a WorkOS contract). Use - for stdin or @/path for a file; an inline value prints a shell-history warning. For Auth0, omit to have one generated. For Clerk, Okta, and WorkOS the secret is required — the CLI checks this (and Clerk’s whsec_ prefix) before making any change. On rotate, --secret - requires --yes — the stdin secret and the confirmation prompt can’t share the same stream.
--yesnoSkip the confirmation prompt on disable / rotate (for CI). Required when rotating with --secret -. Rotating invalidates the previous secret immediately.
--forcenodisable only. Active group-bound grants and group exclusions on policies depend on the webhook for real-time membership revocation, so a plain disable is rejected with a conflict while any exist. --force revokes those grants and removes those exclusions (each change is audit-logged) and then disables webhooks. The cascade is type-to-confirm gated: pass --confirm <issuer-host> or answer the interactive prompt.
--confirm <issuer-host>with --forceConfirms the --force cascade by naming the provider’s exact issuer host (shown by webhook status as issuer_host; case-insensitive). Required in non-interactive (CI / piped) environments where the type-to-confirm prompt cannot run; the backend enforces the same match server-side.
Terminal window
# Enable (Clerk: paste the dashboard secret from a file)
alter identity-providers webhook enable --provider <id> --secret @/run/secrets/whsec
# Check status, rotate, disable
alter identity-providers webhook status --provider <id>
# Rotate (Clerk/Okta/WorkOS require the new secret; Auth0 omits --secret to generate one)
alter identity-providers webhook rotate --provider <id> --secret @/run/secrets/whsec --yes
alter identity-providers webhook disable --provider <id>
# Disable while group-bound grants or group exclusions exist: revoke/remove them and disable
# (type-to-confirm: --confirm must name the provider's issuer host)
alter identity-providers webhook disable --provider <id> --force --confirm acme.okta.com

Preview claim mappings, then create with an explicit user-ID claim

Terminal window
# api://default is the audience of Okta's default *custom* authorization
# server (issuer path /oauth2/default). An org-server issuer (bare
# https://acme.okta.com) never issues api://default tokens — bind it via
# the wallet client pair instead (see the wallet sign-in recipe below).
alter identity-providers discover --issuer-url https://acme.okta.com/oauth2/default
alter identity-providers create \
--issuer-url https://acme.okta.com/oauth2/default \
--audience api://default \
--user-id-claim sub

Create an Auth0 provider for user sign-in

Terminal window
# Auth0 group grants are not currently supported (its Groups feature is
# Early Access), so no group claim is needed — Auth0 handles user sign-in
# and user-principal grants. Use Okta/WorkOS/Clerk for group grants.
alter identity-providers create \
--issuer-url https://acme.us.auth0.com \
--audience https://api.example.com \
--user-id-claim sub

Create a WorkOS provider with stable-ID group keying (enables group grants)

Terminal window
# WorkOS shows the AuthKit domain without a scheme — paste it bare
# (acme-corp.authkit.app) and the CLI prepends https:// for you.
# The audience is the token's exact aud value — the Connect application's
# Client ID (client_...) for the id_tokens used at sign-in.
alter identity-providers create \
--issuer-url acme-corp.authkit.app \
--audience <workos-client-id> \
--group-claim org_id \
--group-claim-is-id

Create with wallet sign-in, secret read from a file (CI-safe)

Here --wallet-client-id supplies the effective audience, so --audience can be omitted.

Terminal window
alter identity-providers create \
--issuer-url https://acme.okta.com \
--wallet-client-id <oidc-client-id> \
--wallet-client-secret @/run/secrets/idp-client-secret

Report an issue with this page

Necessary

Required for sign-in, security, authorization, and remembering your choices.

Always active

Analytics

Helps us understand which product and documentation features are useful.

Performance diagnostics

Uses performance tracing and privacy-masked session replay to diagnose problems.

You can change these choices at any time from Cookie settings.