Skip to main content
Version: 1.6.0

Single Sign-On (SAML)

Single sign-on (SSO) lets the members of an AISIX Cloud organization sign in to the dashboard through your identity provider (IdP) instead of with a password. Each organization configures its own SAML 2.0 connection, so it works with Microsoft Entra ID, Okta, Keycloak, or any other standard SAML IdP. This page covers the configuration and behavior that apply to every IdP. For a step-by-step setup with Microsoft Entra ID, see Integrate with Microsoft Entra ID.

SSO is available in both the SaaS service and On-Premises deployments, on every plan. It is configured in the dashboard, under Settings, on the Single sign-on (SAML) card.

A connection can:

  • sign existing members in through the IdP;
  • add new members on their first sign-in (just-in-time provisioning);
  • set each member's role from the attributes the IdP sends;
  • require non-owner members to use SSO to reach the organization.

SSO complements SCIM directory sync: SCIM creates, updates, and deactivates members ahead of time, and SSO is how those members sign in. You can use either one on its own.

An AISIX Cloud account belongs to the person, not to the organization: the same account can be a member of several organizations. SSO therefore signs a person in to an account only after that account is connected to their identity at the IdP. On an On-Premises control plane the connection is made by email address on the first sign-in. On the SaaS service, the person confirms it on the Connect page, unless the email address is on one of the organization's verified domains. See How a Sign-In Finds the Account.

Who Can Configure SSO​

Only an organization owner can create, change, or remove the SSO connection. Admins see the card read-only, and other roles, including custom roles, do not see it.

The restriction is deliberate: whoever controls the IdP the organization trusts can sign in as any member of the organization, owners included. Choosing that IdP is therefore an owner's decision.

Service Provider Values​

The top of the Single sign-on (SAML) card shows the values you register with your IdP. They are built from the control plane's public URL and the organization's ID:

ValueFormatEntra ID field
Entity ID (Identifier)<public-base-url>/api/auth/sso/saml/<org-id>/metadataIdentifier (Entity ID)
Assertion Consumer Service URL (Reply URL)<public-base-url>/api/auth/sso/saml/<org-id>/acsReply URL (Assertion Consumer Service URL)
Sign-on URL<public-base-url>/login?sso=<org-slug>Sign on URL

The entity ID is also the URL of the service provider metadata document. It is public, so an IdP that imports SP metadata can read it directly, and Download service provider metadata saves the same document. The metadata declares one HTTP-POST assertion consumer service, unsigned authentication requests, and signed assertions.

The entity ID and the reply URL use the organization's ID, not its slug, so the IdP registration keeps working if the slug changes. The sign-on URL uses the slug.

On an On-Premises control plane, <public-base-url> is the value of AISIX_CLOUD_PUBLIC_BASE_URL, or api.publicBaseURL in the Helm chart. It must be the URL browsers use to reach the control plane, because the IdP sends the browser back to it. See Runtime URLs.

Configure Your Identity Provider​

For Microsoft Entra ID, follow the step-by-step guide in Integrate with Microsoft Entra ID. For another SAML 2.0 identity provider, the setup has the same parts:

  1. Register AISIX Cloud with the IdP. Create a SAML application, and enter the entity ID, the assertion consumer service URL, and, if the IdP has such a field, the sign-on URL from the SSO card. An IdP that imports service provider metadata can read it from the entity ID URL instead.
  2. Send a stable name identifier. AISIX Cloud recognizes a returning person by the name identifier (NameID) of the assertion, so the NameID must be a stable identifier of the person that does not change when their email address or user name does, such as an immutable user ID. For Microsoft Entra ID, use user.objectid with the Persistent format. A transient NameID, which changes on every sign-in, is refused with SSO_NAME_ID_TRANSIENT, and an assertion without a NameID is refused with SSO_NAME_ID_MISSING. Choose the NameID before people start signing in: see Changing the NameID Later.
  3. Send the email address. Send each person's email address in the attribute that Email attribute names. Also send a display name, and the attribute your role mapping rules read, if you use any.
  4. Sign, do not encrypt. The IdP must sign the response or the assertion, and must not encrypt the assertion.
  5. Give people access. Assign the people who should sign in to the application, if the IdP requires it.
  6. Copy the IdP metadata into AISIX Cloud. On the SSO card, paste the IdP's metadata into Identity provider metadata XML and select Read metadata, or select Upload metadata file. Check Identity provider entity ID, Single sign-on URL, and Signing certificates, then turn on Enable single sign-on, choose the other options described in Connection Settings, and select Save.

AISIX Cloud reads the identity provider's entity ID, its HTTP-Redirect sign-in endpoint, and its signing certificates from the metadata. It never downloads metadata from a URL, so paste or upload the document itself. You can also skip the metadata and enter the three fields by hand.

Then sign in through the sign-on URL to test the connection.

Rotate the Signing Certificate​

A connection holds up to 10 signing certificates and accepts a response signed by any of them. Each one can be pasted as PEM or as base64-encoded DER, the form metadata documents and IdP consoles show.

To rotate the IdP's certificate without an outage:

  1. Create the new certificate in the IdP, but do not use it for signing yet.
  2. Select Add certificate on the SSO card, paste the new certificate, and save.
  3. Make the IdP sign with the new certificate.
  4. After sign-ins work with the new certificate, remove the old one from the SSO card and save.
  5. Turn Require single sign-on back on.

Adding or removing a certificate turns Require single sign-on off, which is why it is turned back on last. If the IdP signs with a certificate that the SSO card does not hold, every sign-in fails with SSO_RESPONSE_INVALID. For the steps in Entra ID, see Rotate the Signing Certificate in the Entra ID guide.

Connection Settings​

SettingDefaultDescription
Enable single sign-onOffMembers can sign in through the IdP. A connection can be saved disabled while you set it up.
Add new members on sign-in (just-in-time)OffA person the organization does not know yet becomes a member on their first sign-in. See How People Become Members.
Default rolememberThe role of a member added on sign-in, and the role used when role mapping rules exist but none matches. It can be member, admin, or a custom role, never owner.
Email attributehttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddressThe assertion attribute that carries the email address. Leave it empty to use the default.
Display name attributehttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameThe assertion attribute that carries the display name. Leave it empty to use the default.
Identity provider entity ID, Single sign-on URL, Signing certificatesNoneThe IdP the connection trusts. Usually filled from the IdP metadata. The sign-on URL is the IdP's HTTP-Redirect endpoint.
Role mappingNo rulesOrdered rules that set a member's role from IdP attributes. See Map IdP Attributes to Roles.
Require single sign-onOffNon-owner members can reach the organization only through SSO. See Require Single Sign-On.

Attributes are matched by their Name or their FriendlyName, ignoring case. When the email attribute is missing from an assertion, the NameID is used as the email address if it has the form of one. Otherwise the assertion carries no email address. Such a sign-in still works for a person whose identity is already connected to an account, and a first sign-in goes to the Connect page. When the display name attribute is missing, the given name and surname are joined. When those are missing too, the email address is used, and without an email address, the NameID.

Remove connection deletes the connection. Members can no longer sign in through the IdP, and sessions it already opened last until they expire.

Configuration changes are recorded in the audit log with the resource type sso_connection, and a member that SSO adds or whose role it changes is recorded as a member change. Connections between identities and accounts are recorded too; see Identity Links.

SSO Sign-In​

What the sign-in page offers depends on the deployment:

  • On-Premises. The sign-in page never asks for an organization identifier. When the organization has an enabled SSO connection, the page shows a Continue with <organization> SSO button, named after the organization, which sends the member straight to the IdP. Without an enabled connection, the page has no SSO entry at all.
  • SaaS. A member selects Continue with SSO, enters the organization's identifier, which is the slug at the end of the sign-on URL, and is sent to the IdP.

After signing in at the IdP, the member lands in the organization, or on the Connect page the first time their identity is not connected to an account yet. The password form stays on the sign-in page in both deployments, even with Require single sign-on on, because owners can always sign in with their password.

The sign-on URL, /login?sso=<org-slug>, works in both deployments and opens a page with only the Sign in with SSO button for that organization. Share it with members, or register it with the IdP as the sign-on URL so that the IdP's app launcher, such as the My Apps tile in Entra ID, leads there. The member then selects Sign in with SSO on that page.

An On-Premises control plane upgraded from 1.5.x or earlier that still holds several organizations shows no SSO button until they are consolidated into one.

A sign-in must finish in the browser that started it, within 10 minutes. A sign-in that finds the person's account replaces any session the browser already had. A sign-in that ends on the Connect page leaves the browser's session as it was.

The following are not supported:

  • IdP-initiated sign-in. AISIX Cloud refuses a SAML response that does not answer a sign-in it started.
  • Single logout. Signing out of the dashboard ends the AISIX Cloud session only. The IdP session stays.
  • Encrypted assertions. The IdP must sign the response or the assertion, and must not encrypt the assertion.

How a Sign-In Finds the Account​

The first time an identity signs in, AISIX Cloud links the connection and the identity's NameID to an account. Every later sign-in finds the account through that link alone. The email address in the assertion is no longer consulted, so a person whose email address changes at the IdP keeps signing in to the same account. A connection links each NameID to one account, and each account to one NameID.

A link is removed when:

  • the person is removed from the organization, whether in the dashboard, through SCIM, or in any other way;
  • the connection is removed;
  • the Identity provider entity ID changes, which removes every link of the connection.

Changing the IdP's single sign-on URL or its certificates keeps the links.

Links are recorded in the audit log with the resource type sso_identity_link: create when a link is made, with via set to connect, trusted_email, or email_claim; reject when a link is refused because the account is already linked to another NameID; and delete when a link is removed because a verified domain took over an unverified account. The takeover itself is recorded with the resource type verified_domain_claim; see Audit Records. Email verification links that the Connect page sends are recorded with the resource type sso_email_claim, as create when the link is sent and complete when it is used. No token is ever recorded.

First Sign-In​

When no link exists yet, what happens depends on whether AISIX Cloud trusts the IdP for the email address in the assertion:

  • On an On-Premises control plane, the IdP is the operator's own and is trusted for every address.
  • On the SaaS service, every organization controls its own IdP, which could assert anyone's address. The IdP is trusted only for addresses on the organization's verified domains, matched exactly, without subdomains.

With a trusted address, the sign-in links the account that uses the address, ignoring case. When no account uses it, one is created without a password, but only if the organization will admit the person: just-in-time provisioning is on, or the person has a pending invitation. Otherwise the sign-in is refused with SSO_NOT_A_MEMBER and no account is created. The person goes straight into the organization, with no Connect page.

On the SaaS service, an account that uses a trusted address but never verified it was registered by someone who never proved they own the address. The sign-in takes it over: the account loses its password, its sessions, its pending email verification links, and its links to other organizations' SSO connections. It takes the display name from the assertion, the name just-in-time provisioning would give a new account, its acceptance of the User Agreement and Privacy Policy is cleared, and its email address is marked verified. The takeover is recorded as a verified_domain_claim audit entry; see Organization Domains. An account that already verified its address is linked without a takeover and keeps its name. On an On-Premises control plane, no account is taken over: it keeps its name, password, and sessions.

Otherwise, that is on the SaaS service for an address outside the verified domains, and in either deployment for an assertion without an email address, the person goes to the Connect page.

The Connect Page​

The Connect page, /sso-connect, says that the person authenticated through the organization's SSO, with which email address, and that the identity is not connected to an account yet. The identity waits there for 10 minutes, in the browser where the sign-in happened. Nothing is linked until the person confirms. The page offers these ways forward:

  • Log in to an existing account. The person signs in with the password of any account, then confirms. When the browser is already signed in, the page offers Connect as <email> for that account, and Use another account. On the SaaS service, the account's email address must be verified first, as for every password sign-in.
  • Create a new account. The email address is the one the IdP sent and cannot be changed. The person verifies it like any new account. After signing in from the verification link, the browser returns to the organization's SSO sign-in page, and the person signs in through SSO again and confirms. This option is not offered when the assertion has no email address, when the address belongs to an account without a password, or when the deployment creates accounts only from invitations, as an On-Premises control plane does.
  • Send a verification link. When the email address in the assertion belongs to an existing account without a password, such as one SCIM provisioned or, on an On-Premises control plane, one an administrator created, the page offers Send a verification link to <email> instead of creating an account. The link is valid for one hour, works once, and stops working when a newer one is sent. It does not depend on the browser, so it can be opened anywhere. It opens a page that names the organization, by name and identifier, and the account. Connect and sign in connects the identity, marks the email address verified, and signs in. The account still has no password afterwards. If the browser is signed in to another account, the page says that connecting signs it out.

An account with a password can be connected only by logging in to it.

caution

Connecting an account lets that organization's IdP sign in as the account from then on, with no password. The session it opens is an ordinary session of the account, so it reaches every organization the account belongs to, except organizations that require their own single sign-on. Connect only an account that you want this IdP to control.

A session that still has to change its password cannot connect: the request is refused with PASSWORD_CHANGE_REQUIRED. Change the password first.

Changing the NameID Later​

A connection never replaces a link. When the IdP starts sending a different NameID for a person, for example because you changed the IdP's NameID source, or because the NameID was a user name that has since been renamed, the person is refused with SSO_ACCOUNT_ALREADY_LINKED. To let them sign in again, remove them from the organization, which removes the link, and add them back.

Replacing the link automatically would be unsafe: an IdP that lets users change their own email address could otherwise hand an account that is already linked to someone else.

How People Become Members​

Once the account is known, the organization decides whether to admit it:

  • The person is already a member of the organization, whether invited, created in the dashboard, or provisioned through SCIM: they are signed in. A member provisioned through SCIM stays managed by SCIM.
  • The person is a SCIM member waiting to join, and the NameID equals the externalId the directory sent: connecting the identity activates the member. See Members Waiting to Join.
  • The person has a pending invitation to the organization, issued to the account's verified email address, or to the trusted address the IdP sent: the invitation is accepted, and they join with the invitation's role, unless role mapping rules set a different one.
  • None of these, with just-in-time provisioning on: they join with the default role, or the role the rules give them. An existing account, for example one that belongs to another organization, is added to this organization.
  • None of these, with just-in-time provisioning off: the sign-in is refused with SSO_NOT_A_MEMBER, and no link is made. Invite the person, or provision them through SCIM.

A member whose membership is deactivated, for example by SCIM, cannot sign in. The sign-in is refused with SSO_MEMBER_DEACTIVATED.

An account created by SSO has no password. On an On-Premises control plane, an admin can still enable password sign-in for it.

Map IdP Attributes to Roles​

Role mapping rules set a member's role from the attributes in the SAML assertion. A connection holds up to 50 rules. Each rule names an attribute, an operator, a value, and a role:

OperatorDashboard labelMatches when
exact_matchequals (first value)The attribute's first value equals the value.
contains_stringcontains (first value)The attribute's first value contains the value.
exact_match_in_arrayany value equalsAny value of the attribute equals the value.
contains_string_in_arrayany value containsAny value of the attribute contains the value.

Attribute names are matched by Name or FriendlyName, ignoring case. Values are compared exactly, including case. The rules are checked in order, and the first match wins.

What the rules change:

  • With rules, every sign-in sets the member's role to the role of the first matching rule, or to the default role when no rule matches. This also overrides the role of an invitation the member accepts by signing in, and a role changed by hand in the dashboard, at the member's next sign-in.
  • Without rules, SSO sets the role only when a person joins: the invitation's role, or the default role. After that, SSO never changes it.
  • Owners are never changed by SSO, with or without rules.

When the organization also uses SCIM, a role SSO wrote wins: SCIM group-to-role mappings no longer change that member's role. Removing every rule, or removing the connection, hands those roles back to SCIM, and so does changing the member's role by hand.

A custom role named by the default role or a rule cannot be deleted while the connection uses it.

For Microsoft Entra ID, the guide shows how to define app roles and map them to AISIX Cloud roles.

Require Single Sign-On​

Require single sign-on makes SSO the only way for non-owner members to reach the organization. It can be turned on only for an enabled connection.

With it on:

  • A member who is not an owner can open the organization only with a session that completed this organization's SSO within the last 24 hours, by signing in through it or by confirming on the Connect page. The 24 hours count from that sign-in and are not extended by using the session. SSO with another organization does not count. Otherwise, the dashboard sends them to the Single sign-on required page, /sso-required?org=<org-slug>, which offers SSO sign-in, and API calls return 403 with the error code SSO_REQUIRED. The organization still appears in their organization list, so they can find it.
  • Owners are exempt. They can always sign in with their password, which keeps a way in if the IdP fails or is misconfigured.
  • Existing admin tokens keep working.

Changing the identity provider entity ID, its single sign-on URL, or its certificates, including adding a certificate, turns enforcement off automatically. The new IdP settings have not been proven by a sign-in yet. Sign in through the IdP once, then turn the setting back on.

SSO Sessions​

A session that SSO opens is an ordinary session of the account, the same as a password session:

  • It reaches every organization the account belongs to, subject to each organization's Require single sign-on setting.
  • It lasts 7 days and is extended while it is in use.
  • It can change the account's profile and password, create organizations, and redeem invitations, like any other session.

When the browser was already signed in as the same person, the new session keeps the record of the SSO sign-ins the previous session completed, so signing in through one organization's SSO does not cost another organization the SSO sign-in it already has.

Troubleshooting​

When an SSO sign-in does not complete, the browser returns to /login?sso=<org-slug>&sso_error=<CODE>, and the page explains the error. On an On-Premises control plane, cp-api also logs why it refused a SAML response.

CodeLikely causeFix
SSO_NOT_ENABLEDNo organization has this identifier, or its SSO connection is disabled. Also returned when the connection was disabled or replaced during the sign-in.Check the identifier, and that Enable single sign-on is on.
SSO_UNSOLICITED_RESPONSEThe response does not answer a pending sign-in: the IdP started the sign-in itself, the sign-in is older than 10 minutes, or the response was already used.Start from the AISIX Cloud sign-in page. Register the sign-on URL with the IdP, such as the Entra ID Sign on URL, so that its app launcher opens the AISIX Cloud sign-in page.
SSO_RESPONSE_INVALIDThe response failed validation. It may be signed by a certificate the connection does not hold, come from another issuer, name another audience or recipient, or fall outside its validity period.Compare the Identity provider entity ID and the certificates with the IdP, and the entity ID and reply URL registered with the IdP with the SSO card. Check the clocks of the IdP and the control plane.
SSO_ENCRYPTED_ASSERTION_UNSUPPORTEDThe IdP encrypted the assertion.Turn off token or assertion encryption for the application in the IdP.
SSO_IDP_ERRORThe IdP answered with a failure status.Check the IdP's sign-in logs for the reason.
SSO_NAME_ID_MISSINGThe assertion has no NameID.Configure the IdP to send a NameID for every user.
SSO_NAME_ID_TRANSIENTThe NameID has the transient format, which names the person for one sign-in only.Send a persistent NameID, or another format that stays the same for a person, such as an immutable user ID. With Entra ID, use user.objectid with the Persistent format.
SSO_BROWSER_MISMATCHThe sign-in finished in a browser other than the one that started it, took more than 10 minutes, or the browser blocked the sign-in cookie.Start again from the sign-in page, in one browser.
SSO_NOT_A_MEMBERThe person is not a member, has no pending invitation, and just-in-time provisioning is off.Invite the person, provision them through SCIM, or turn on Add new members on sign-in (just-in-time).
SSO_MEMBER_DEACTIVATEDThe membership is deactivated.Reactivate the member, for example in the IdP when SCIM manages them.
SSO_ACCOUNT_ALREADY_LINKEDThe account is already linked to a different NameID at this connection, usually because the IdP's NameID for the person changed.Remove the person from the organization and add them back. See Changing the NameID Later.
SSO_IDENTITY_ALREADY_LINKEDOn the Connect page: the identity was connected to another account in the meantime.Sign in through SSO again, which signs in to that account.
SSO_CONNECT_EXPIREDOn the Connect page: the browser holds no identity waiting to be connected. It was connected already, or more than 10 minutes passed.Sign in through SSO again.
SSO_CLAIM_LINK_INVALIDThe verification link sent from the Connect page is invalid, expired, already used, or replaced by a newer one.Sign in through SSO again and send a new link.
INTERNAL_ERRORThe control plane failed while handling the sign-in.Try again. On an On-Premises control plane, check the cp-api logs.

If the IdP itself reports that the reply URL does not match, such as AADSTS50011 in Entra ID, or every response fails with SSO_RESPONSE_INVALID, check the public base URL first. The SSO card builds the entity ID and the reply URL from it, so a value that browsers cannot reach, or one that changed after you registered the application, breaks every sign-in. Correct AISIX_CLOUD_PUBLIC_BASE_URL or api.publicBaseURL, then copy the new values from the SSO card to the IdP.

Errors that Entra ID shows on its own pages, such as AADSTS50105 for a user who is not assigned to the application, are covered in the Entra ID guide's Troubleshooting.

Next Steps​

Use SCIM Directory Sync to provision and deprovision members from the same IdP, and Roles and Custom Roles to define the roles that SSO assigns.