Skip to main content

Portal Login (SSO): SAML and OIDC

This page covers plane (a), portal login: a human signing into the AxonFlow customer portal in a browser through your corporate identity provider. For the full picture of how portal login relates to per-user fleet identity and SCIM provisioning, start with the three planes of identity.

AxonFlow supports both protocols for portal login:

  • SAML 2.0 interactive login. Works end-to-end for self-hosted (in-vpc) deployments as of v9.15.0.
  • OIDC interactive login (browser authorization-code flow). Available as of v9.16.0.

Either protocol ends the same way: a validated assertion or id_token creates an authenticated portal session. Both are Enterprise capabilities.

Portal login is one of three identity planes

Portal login (this page) is a human signing in through a browser. It is not the same as per-user fleet identity (a tool carrying an X-User-Token OIDC token on API calls) or SCIM provisioning (syncing the user directory and roles). OIDC appears in two of those planes: as a portal login protocol here, and as fleet token verification there. They are configured separately.

What SSO solves

Portal SSO matters when AxonFlow is used by more than one or two engineers and starts to involve operations teams, compliance reviewers, platform administrators, and approvers who need portal access. Instead of managing separate AxonFlow passwords per person, you authenticate those users through the identity provider they already use, which gives you centralized authentication policy, MFA enforcement at the identity provider, faster onboarding and offboarding, and a cleaner audit posture.

Portal login does not affect SDK or service-to-service authentication, which continues to use Basic auth with client credentials.

Choosing a protocol

SAML portal loginOIDC portal login
Available sincev9.15.0 (in-vpc end-to-end)v9.16.0
Provider valuesokta, azure_ad, auth0, custom_samloidc, jumpcloud
Login route/auth/saml/{sso-tenant}/login/auth/oidc/{sso-tenant}/login
Callback route/auth/saml/{sso-tenant}/callback (ACS)/auth/oidc/{sso-tenant}/callback (redirect_uri)
Setup helpersmetadata fetch, SP metadata, per-provider defaultsissuer / audience / JWKS + client credentials

Both protocols create the same kind of portal session and both resolve roles the same way (from SCIM, never from a token or assertion claim). Pick whichever your identity provider exposes most cleanly; a single provider such as JumpCloud or Okta can offer both.

If you also run fleet identity, portal login must be OIDC

A tenant has one SSO configuration, either SAML or OIDC. Per-user fleet identity (plane b) requires that configuration to be OIDC, so a tenant that runs fleet tokens must also use OIDC for portal login: one OIDC configuration drives both. SAML portal login and fleet OIDC cannot run on the same tenant. If you do not use fleet identity, either protocol is fine.

SAML portal login

The SAML flow is service-provider-initiated:

  1. A user navigates to the AxonFlow portal login page.
  2. The portal resolves the user's SSO tenant and redirects to /auth/saml/{sso-tenant}/login, which generates a SAML AuthnRequest and sends the browser to the configured identity provider.
  3. The identity provider authenticates the user (password, MFA, or whatever it requires).
  4. The identity provider posts a signed SAML Response back to AxonFlow's Assertion Consumer Service (ACS) URL, /auth/saml/{sso-tenant}/callback.
  5. AxonFlow validates the assertion signature, extracts the user attributes, and writes an authenticated portal session.

An IdP-initiated launch (the user starts in the corporate app portal and clicks AxonFlow) is also supported: the identity provider posts the assertion straight to the ACS URL.

Each SAML provider configuration stores the entity ID, SSO URL, single-logout (SLO) URL, ACS URL, and the identity provider's X.509 certificate for signature verification. AxonFlow can also fetch and parse identity-provider metadata for you; see SSO Configuration.

SAML certificate operations

SAML outages more often come from certificate lifecycle than from protocol misunderstandings, so plan rotation with an overlap window:

StepRecommended timing
Generate the replacement certificateabout 30 days before expiry
Upload and test the new certificatebefore cutover
Update the identity-provider trust configbefore the current certificate expires
Switch traffic to the new certificateduring the overlap window
Remove the old certificateafter the transition is stable

OIDC portal login

The OIDC flow is a browser authorization-code login, new in v9.16.0:

  1. The user is sent to /auth/oidc/{sso-tenant}/login. AxonFlow discovers the authorize and token endpoints from the configured issuer, mints a signed state (CSRF) and nonce (replay) cookie, and 302-redirects the browser to the identity provider's authorize endpoint with the tenant's client_id, an SSO_BASE_URL-derived redirect_uri, and scope openid email profile.
  2. The identity provider authenticates the user and redirects back to /auth/oidc/{sso-tenant}/callback with an authorization code.
  3. AxonFlow validates the signed state and nonce against the cookie, exchanges the code at the token endpoint using client_secret_basic, and verifies the returned id_token: signature against the identity provider's JWKS (RS256), issuer, audience equal to the client_id, expiry, and azp for multi-audience tokens.
  4. On success AxonFlow writes an authenticated portal session.

OIDC portal login needs a client secret, unlike token-verification-only OIDC (plane b). Migration core/158 adds oidc_client_id and oidc_client_secret to the SSO configuration; the client secret is stored with the same at-rest posture as a SAML private key (never returned in a response, never logged). The redirect_uri you must register at the identity provider is https://<your SSO_BASE_URL host>/auth/oidc/<sso-tenant>/callback, and it is surfaced back to you on the config read so you can copy it exactly.

Internal identity providers need AXONFLOW_OIDC_ALLOW_PRIVATE

OIDC endpoint fetches (discovery, JWKS, token exchange) are SSRF-hardened: by default AxonFlow blocks identity-provider hosts that resolve to a private address (RFC-1918, CGNAT, link-local, or a Kubernetes ClusterIP / *.svc.cluster.local). If your identity provider runs inside your own network (an internal Keycloak, ADFS, or PingFederate), set AXONFLOW_OIDC_ALLOW_PRIVATE=true on the agent and customer-portal after upgrading, or every OIDC fetch fails closed. Public-identity-provider SaaS deployments need no change. This is the same hatch the fleet-identity plane uses.

Self-hosted requirement: SSO_BASE_URL

Self-hosted (in-vpc) deployments must set SSO_BASE_URL to the portal's external URL, for example https://portal.yourcompany.com, before configuring portal login. Both the SAML ACS URL and the OIDC redirect_uri are derived from it and recomputed on every request, so the identity provider returns the assertion or authorization code to your own portal rather than the default SaaS host. If SSO_BASE_URL is unset on a non-SaaS deployment, login cannot complete and the portal logs a loud warning at startup. Setting the variable and restarting corrects any previously stored ACS URL with no re-save.

The {sso-tenant} addressing key in the routes above is __platform__ on in-vpc deployments (one platform-wide configuration) and your organization id on SaaS. The pre-login availability check returns the correct login URL for the configured protocol, so a portal client does not need to know in advance whether the tenant uses SAML or OIDC.

Roles come from SCIM, not from the login

Roles are always resolved from the SCIM group-to-role mapping, the audited directory, never from a role or groups claim inside a SAML assertion or an OIDC id_token. An identity-provider claim misconfiguration therefore cannot escalate anyone's access.

When the SSO configuration has Auto-provision users enabled, a first-time SSO user (one with no existing active role in the organization) is assigned their group-mapped role, or the configured default role, on login (SAML since v9.15.0; OIDC role provisioning is best-effort and never blocks login). This is assign-if-absent: a user who already has a role from SCIM, manual assignment, or a prior login is left untouched. Auto-provisioning does not remove a role when the identity provider removes the user from a group; for full add-and-remove lifecycle, run SCIM group-to-role mapping. See SSO Configuration for the setup detail.

Public and private setup detail

Use this public page, SSO Configuration, and the SCIM guides for the generic identity model and rollout sequence. Keep customer-specific identity-provider metadata, tenant URLs, certificates, screenshots, and support context in private partner packs or secure support channels.