Documentation

Access Control & Single Sign-On

Overview

Every change in Veltrix is attributable to a person or an API key, so who can sign in — and what they can do once they have — is platform-level machinery, not an afterthought. The Access Control area of the portal brings it together in three tabs:

User Management

Create, edit, and remove the people in your organization; assign each a role. Users can hold local credentials or be pinned to a single sign-on provider.

Role Management

Fine-grained, resource-by-action permissions across the change lifecycle, including per-app permissions declared by installed integrations.

Identity Provider

Wire sign-in to your existing IdP — AWS Cognito, Google, Microsoft Entra ID, or any OIDC-conformant provider — with per-organization overrides and controlled user provisioning.

Local email + password sign-in works on every plan. Access management — custom roles and identity provider configuration — is available on paid plans; see Pricing.

Users & Roles (RBAC)

Roles are collections of resource : action permissions (for example configuration-canvas:write, credential:read, or apiKey:write). The role catalog is live: it always reflects the platform's enforced resources plus the permissions each installed app declares, so a role can grant app-scoped rights as precisely as platform ones.

  • Fail-closed everywhere. Permissions are enforced server-side on every route; the UI additionally hides what you cannot do rather than letting requests fail late.
  • No self-escalation. An admin can only grant permissions they themselves hold, and cannot promote a user (including themselves) above their own privilege level.
  • Tenant-scoped by construction. Users, roles, and every lookup between them resolve inside your own organization — a role or user ID from another tenant can never be attached.
  • API keys are role-bound. Automation and AI agents authenticate with scoped, revocable, expiring keys bound to a role — see the MCP Server and AI Guardrails guides.

Identity Providers

Veltrix ships four production single sign-on integrations. Each is configured entirely from the portal (Access Control → Identity Provider) and takes effect immediately — configuration is read per-request, so there is no server restart or cache to wait out.

Provider Protocol Notes
AWS Cognito OIDC (Hosted UI) Sign-in via your user pool's Hosted UI. Optional AWS credentials let Veltrix manage pool users from the portal (create/delete), with an environment-variable fallback.
Google OAuth 2.0 / OIDC Google Workspace or consumer Google accounts via a standard OAuth 2.0 web client.
Microsoft Entra ID (Azure AD) OAuth 2.0 / OIDC Single-tenant or multi-tenant app registrations (common, a tenant GUID, or a verified domain).
Generic OIDC OpenID Connect Bring your own issuer: works with any OIDC-conformant provider — Okta, Auth0, Keycloak, PingFederate, and others — via standard discovery and JWKS verification.
SAML SAML 2.0 Coming soon. SAML-only IdPs that also expose an OIDC interface can use the Generic OIDC provider today.

Local email + password authentication stays available alongside SSO — each user record carries its own authentication provider, so a mixed organization (some local accounts, some SSO) works without special setup.

Provider Setup Guides

All providers follow the same shape: register an application with the IdP, allow the Veltrix redirect URI, and paste the client credentials into the provider's card. The portal pre-fills the redirect URIs for your own host — the values below use <your-veltrix-host> as a placeholder.

Every provider is a confidential client. Veltrix redeems the authorization code server-side using the client secret, so register a web / server-side application — never a single-page or public client. This is the most common setup mistake, and each provider reports it differently (Microsoft returns AADSTS9002327).

Generic OIDC (Okta, Auth0, Keycloak, …)

  • Create a web application in your IdP, using the authorization code flow with a client secret, and allow the redirect URI https://<your-veltrix-host>/oauth/callback.
  • Issuer is the provider's base URL — Veltrix fetches {issuer}/.well-known/openid-configuration for discovery, so the issuer must serve a discovery document.
  • Grant the scopes openid email profile. The ID token must carry an email claim — that is what matches an existing account or drives provisioning.
  • No API permissions beyond those scopes are required; Veltrix reads the verified ID token and calls no further endpoint.

Google

  • Google Cloud Console → APIs & Services → Credentials → create an OAuth 2.0 Client ID of type Web application.
  • Add https://<your-veltrix-host>/oauth/callback to the authorized redirect URIs. No authorized JavaScript origin is needed — the browser never calls Google directly.
  • Copy the Client ID and Client Secret into the Google card.
  • On the OAuth consent screen, add the scopes openid, email, and profile. No Google API needs enabling — sign-in verifies the ID token rather than calling an API.
  • Publish the consent screen, or add each person as a test user — while the app is in Testing, anyone not listed is refused.

Microsoft Entra ID (Azure AD)

  • Azure Portal → Microsoft Entra ID → App registrations → register (or reuse) an application.
  • Add https://<your-veltrix-host>/oauth/callback under platform Web — not Single-page application, which rejects the server-side code exchange with AADSTS9002327. Create a client secret under Certificates & secrets.
  • API permissions → Microsoft Graph → Delegated: openid, email, profile, User.Read. This provider reads your profile from Graph /me, so User.Read is required. No application permissions and no .All scopes are needed — Veltrix never reads your directory.
  • Admin consent is optional but recommended: it avoids a per-user consent prompt, and is required if your tenant disables user consent.
  • Tenant ID: use common for multi-tenant sign-in, or your directory's GUID / verified domain to restrict sign-in to one tenant.

AWS Cognito

  • You need a user pool with a Hosted UI domain and an app client. The User Pool ID has the form <region>_<id> (e.g. us-east-1_abcd1234).
  • In the app client settings, allow the callback URL https://<your-veltrix-host>/auth/cognito/callback and the sign-out URL https://<your-veltrix-host>. Note this provider's callback path differs from the others.
  • Generate a client secret, enable the authorization code grant, and allow the OpenID Connect scopes phone openid email.
  • Domain is the Hosted UI host name only — e.g. your-app.auth.us-east-1.amazoncognito.com, with no https:// and no path. Sign-in cannot work until the Hosted UI is configured on the pool.
  • The AWS Access Key ID / Secret Access Key fields are optional and only used for admin operations (listing, creating, and deleting pool users from the portal). Sign-in itself never needs them; when left blank, Veltrix falls back to server environment credentials if present.
  • When you do supply them, the IAM identity needs exactly four actions, scoped to that one user pool:
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": [
      "cognito-idp:ListUsers",
      "cognito-idp:AdminCreateUser",
      "cognito-idp:AdminSetUserPassword",
      "cognito-idp:AdminDeleteUser"
    ],
    "Resource": "arn:aws:cognito-idp:<region>:<account-id>:userpool/<user-pool-id>"
  }]
}

Global vs Organization Scope

Every provider can be saved at one of two scopes, chosen per save with the Configuration scope selector:

  • Global default — applies to every organization on the instance that has no override of its own. Typical for self-hosted, single-company deployments.
  • This organization only — a per-tenant override. The login flow resolves the signing keys, client credentials, and provisioning policy from the organization the sign-in belongs to; anything not overridden falls back to the global default.

Reset to Global Settings deletes only your organization's override and returns you to the shared default. Saving is change-aware: only providers you actually edited are written, disabling a provider is persisted rather than silently discarded, and a failure is reported per provider with the server's actual reason.

Turning a provider off at organization scope removes your override rather than blocking the provider outright — if a global default is enabled, sign-in falls back to it. To stop a provider entirely on a self-hosted instance, disable it at global scope too.

Just-in-Time (JIT) Provisioning

What happens when someone your IdP vouches for signs in but has no Veltrix account yet? Each provider configuration carries its own answer — the New user provisioning (JIT) mode:

Mode Behavior
Match email domain default The domain of the email your identity provider asserts is matched to an organization's registered domain (e.g. alice@acme.com → Acme) and the user is created there with the organization's default User role. An unrecognized domain is rejected with a clear message — never silently dropped into another organization.
Do not auto-create Only users who already exist in Veltrix can sign in through this provider. New identities are rejected and told to contact their administrator — pair with pre-provisioning for a fully admin-controlled roster.
First active organization legacy Every first-time sign-in lands in the first active organization. Kept only for configurations that historically relied on it; not recommended on multi-tenant instances.

Returning users are matched by their provider account ID or email address, so an existing local account with the same email simply gains SSO — no duplicate is created.

Pre-Provisioning SSO Users

Admins can create users ahead of their first sign-in, pinned to an authentication provider (LOCAL, COGNITO, GOOGLE, AZURE, or OIDC) via User Management or POST /api/users:

  • The Authentication provider picker in the Add-user dialog lists only the providers actually enabled for your organization — pinning someone to a provider that isn't configured would leave them unable to sign in at all.
  • SSO users are created with their real email, a role of your choosing, and no local password — they authenticate only at the identity provider.
  • Their first SSO login claims the account by the email the identity provider asserts, and links the provider identity to it permanently.
  • Combined with JIT mode Do not auto-create, this gives you an explicit, admin-curated roster: the IdP authenticates, Veltrix decides who has an account and what role they hold.
  • Cognito is the exception: those users are mirrored into the user pool at creation and receive a temporary password by email, so they are managed from the pool rather than pre-provisioned this way.

How SSO Login Works

  1. The login page is email-first: after you enter your email, Veltrix routes you by your account's provider — a password prompt for local accounts, or a redirect to your IdP for SSO accounts. A Continue with SSO option is shown whenever an OIDC provider is enabled, so brand-new users (who have no account to look up yet) can still start a JIT sign-in.
  2. Veltrix mints a one-time, server-side state and nonce bound to your organization's provider configuration, and sends you to the IdP's authorization page.
  3. After you authenticate (including any MFA your IdP enforces), the IdP redirects back with an authorization code. Veltrix consumes the one-time state and exchanges the code for tokens. For AWS Cognito, Google, and generic OIDC the ID token is then cryptographically verified against the provider's published signing keys — issuer, audience, expiry, and nonce all have to match. Microsoft Entra ID sign-ins instead resolve your identity from Microsoft Graph over TLS, bound to the one-time nonce this server issued (which is why that provider requires it).
  4. Only then is the user resolved (returning-user match or JIT provisioning per the configured mode), the same account gates applied as for local login, and a Veltrix session issued.

Deactivated user or suspended organization? SSO enforces exactly the same gates as local login — a deactivated account or an inactive organization is rejected even with a perfectly valid IdP token.

Security Properties

  • Real signature verification. For AWS Cognito, Google, and generic OIDC, ID tokens are verified against the provider's JWKS with issuer and audience checks — unsigned or wrongly-signed tokens are rejected, with automatic recovery when the IdP rotates signing keys.
  • Replay protection. The sign-in state is single-use and consumed server-side, as is the nonce bound to it — a replayed sign-in link fails rather than producing a second session.
  • Secrets stay secret. Secret values — client secrets and the AWS secret access key — are encrypted at rest and never returned by any API. The settings UI shows only a "configured" flag with an explicit Replace secret action, and saving other fields never wipes a stored secret. (Non-secret identifiers such as the client ID and AWS access key ID are returned, as they necessarily appear in the browser-visible sign-in flow.)
  • Tenant isolation. The organization a configuration read or save applies to is resolved from the verified session, never from a client-supplied header.
  • Hardened outbound fetches. OIDC discovery and JWKS lookups validate that the issuer resolves to a public host before fetching (SSRF protection).
  • MFA in the right place. Local accounts can enable TOTP two-factor authentication in Veltrix; for SSO accounts, MFA is enforced by your identity provider — the IdP owns the authentication ceremony, Veltrix owns authorization.

Test Connection

Each provider's Configure dialog has a Test connection button that validates the values currently in the form — before anything is saved — and reports truthful, specific results:

  • For OIDC/Google/Microsoft: is the issuer or tenant discoverable, and does the token endpoint accept your Client ID / Client Secret pair? A typo'd secret is distinguished from an unreachable provider.
  • For Cognito: does the user pool exist in the given region, and is the Hosted UI domain reachable and accepting your app client credentials?
  • A blank secret field tests against the currently stored secret, so you can re-validate a working configuration without re-typing it.

Troubleshooting

Symptom Likely cause & fix
"No organization is configured for the domain …" JIT is in domain-match mode and the user's email domain isn't registered to any organization. Register the domain on the organization, or pre-provision the user.
"Your account has not been provisioned for single sign-on" JIT is disabled for this provider and no matching account exists. Create the user first (see pre-provisioning).
"This sign-in link has expired or was already used" The one-time login state/nonce was replayed or timed out (10-minute window). Start the sign-in again from the login page.
"… sign-in is not configured or is disabled" The provider is disabled at the scope this login resolves to. Check both your organization's override and the global default.
"Your account has been deactivated" / "Your organization's account is not active" The same account gates as local login. An administrator must reactivate the user; a suspended organization must be restored first.
Test Connection: "rejected the Client ID / Client Secret pair" The IdP is reachable but refused the credentials — re-copy both values, and if the secret was rotated at the IdP, use Replace secret and save.