Skip to Content

Single Sign-On & SCIM

Open Settings → SSO in the Control Center to connect your identity provider (IdP). The tab has three cards:

CardWhat it does
SAMLSign in to the Control Center with a SAML 2.0 IdP (Okta, Entra ID, OneLogin, JumpCloud, …)
OIDCSign in with an OpenID Connect provider (Google Workspace, Okta OIDC, Keycloak, Auth0, …)
SCIM provisioningLet Okta or Azure AD (Entra ID) create, update and remove Control Center users and map groups to roles

Each card shows its status (connected, off or error), the IdP host or your sign-in domain, and how many people use it.

Sign-in buttons on the login page

The login page shows Continue with Google, Continue with GitHub and Continue with SAML SSO / SSO buttons:

  • Your workspace’s SSO buttons appear once someone types an email address from a domain your workspace has verified (see Verify your sign-in domain). The page never shows your workspace name. It shows only a generic button.
  • Google and GitHub buttons appear for everyone when the operator of the Control Center enabled them (see Operator setup). They sign in existing accounts whose email matches the verified email of the Google or GitHub account.

After the IdP round trip you land where you were going (for example back on the fleet page). If your account uses two-factor authentication, you still enter your TOTP code.

Sign-in is refused, with a message on the login page, when:

Message codeMeaning
no_accountNo Control Center account for that email (and it could not be created, see below)
not_provisionedYour workspace uses SCIM, and the IdP has not provisioned you yet
account_disabledYou were deprovisioned in this workspace (or in every workspace, for Google / GitHub)
email_unverifiedThe IdP did not confirm your email address
account_conflictThe account could not be added to this workspace
tenant_suspendedThe workspace is suspended
idp_misconfigured / invalid_assertion / invalid_id_tokenThe connector settings or the IdP response are wrong. Ask your admin

People in several workspaces

One Quazzar account can belong to several workspaces:

  • Signing in through your workspace’s SAML or OIDC connector opens your workspace only. That session cannot switch to the person’s other workspaces; they sign in with their password, Google or GitHub for that.
  • Google and GitHub sign-in lands in the workspace that verified the email’s domain, otherwise in the workspace the person used last.
  • When SCIM or just-in-time sign-in adds someone who already has an account in another workspace, this workspace is added to their account. Their password is not changed, and SCIM here cannot change their email or name while the account also belongs to another workspace.
  • Deactivating someone through SCIM only removes their access to your workspace.

Just-in-time accounts

When someone signs in through your workspace’s SAML or OIDC connector with an email in a verified domain and has no account yet, the Control Center creates one with the Viewer role. It does not do this when SCIM provisioning is on: then SCIM is the only way accounts are created.

Verify your sign-in domain

Owners and admins add the email domain in Settings → SSO → Sign-in domains:

  1. Enter your domain, for example acme.com. Public mail domains (gmail.com, outlook.com, …) are not allowed.

  2. Publish the TXT record shown:

    _quazzar-sso.acme.com. TXT "quazzar-sso-verification=<token>"
  3. Click Verify. Once DNS has propagated, the domain is marked verified. If the record isn’t visible yet the domain shows record not found and keeps the record on screen; if another workspace already verified the domain it shows claimed elsewhere.

Only one workspace can verify a domain. Until you verify it, the domain does not route sign-ins to your workspace.

Connect a SAML IdP

  1. In Settings → SSO → SAML, click Configure and choose the SAML connector.

  2. In your IdP, create a SAML 2.0 app with:

    IdP fieldValue
    Single sign-on URL / ACS URLhttps://<control-center>/api/auth/sso/saml/<connector-id>/acs
    Audience / SP Entity IDhttps://<control-center>/api/auth/sso/saml/<connector-id>/metadata
    Name ID formatEmailAddress (recommended)
    Attribute email (or mail)the user’s email

    The SP metadata XML is also available at the Entity ID URL above.

  3. Paste the IdP’s settings into the connector configuration:

    KeyDescription
    idp_metadata_urlIdP metadata URL (Okta: View SAML setup instructions → IdP metadata)
    idp_metadata_xml…or the metadata XML itself
    sso_url + ca…or the IdP SSO URL plus its signing certificate (PEM)
    email_attributeOptional: attribute name holding the email, if it is not email / mail
    sp_certificate + sp_private_keyOptional: key pair for encrypted assertions

Only SP-initiated sign-in (from the Control Center login page) is supported. IdP-initiated tiles in the Okta dashboard are refused.

Connect an OIDC provider

Create a web application in your IdP with the redirect URI

https://<control-center>/api/auth/sso/callback/<connector-id>

and set the connector configuration:

KeyDescription
issuerIssuer URL, for example https://acme.okta.com or https://accounts.google.com
client_idOAuth client ID
client_secretOAuth client secret
scopesOptional extra scopes (list)

The Control Center uses the authorization-code flow with PKCE and a nonce, and signs in the user whose email the ID token asserts. An ID token with email_verified: false is refused.

SCIM provisioning

🔒 Business plan and above. SCIM provisioning is part of the Business and Enterprise plans. SAML and OIDC sign-in are not affected. See Control Center features by plan.

SCIM 2.0 (RFC 7643 / 7644) lets your IdP manage Control Center users:

  • Create a user when you assign someone to the app. If an account with that email already exists in your workspace, SCIM links it instead.
  • Update name and email when they change in the IdP.
  • Deactivate (active = false) or delete a user when you unassign or suspend them. Their access to your workspace is blocked immediately, their sessions in it are ended and issued tokens are revoked. Other workspaces they belong to are not affected. The account row is kept, so tickets and audit history stay intact.
  • Groups → roles: push groups and map them to Control Center roles.

The workspace owner is never deactivated, deleted or re-roled by SCIM. Such requests fail with a mutability error so you can see them in the IdP’s provisioning log.

Enable SCIM

  1. Open Settings → SSO and click Enable on the SCIM provisioning card, then name the first token and click Create token. (New token in the SCIM panel creates more.)
  2. Copy the token. It is shown once. Only a hash is stored. You can create more tokens, rotate a token (the old one stops working at once) or revoke it.
  3. Note the SCIM base URL: https://<control-center>/scim/v2.

Okta

  1. In Okta, open your Quazzar app (or create a SAML app first), then General → App Settings → Edit → Provisioning: SCIM and save.
  2. On the Provisioning tab → Integration → Edit:
    • SCIM connector base URL: https://<control-center>/scim/v2
    • Unique identifier field for users: userName
    • Supported provisioning actions: Push New Users, Push Profile Updates, Push Groups
    • Authentication Mode: HTTP Header, and paste the SCIM token as the Bearer token
  3. Click Test Connector Configuration, then Save.
  4. Provisioning → To App: enable Create Users, Update User Attributes and Deactivate Users.
  5. Assign people or groups on the Assignments tab. To map roles, push groups on the Push Groups tab.

Azure AD / Microsoft Entra ID

  1. Enterprise applications → New application → Create your own application (“Integrate any other application you don’t find in the gallery”).
  2. Provisioning → Get started, and set Provisioning Mode to Automatic.
  3. Admin credentials:
    • Tenant URL: https://<control-center>/scim/v2
    • Secret Token: the SCIM token
  4. Click Test Connection, then Save.
  5. Under Mappings, keep Provision Microsoft Entra ID Users and Groups enabled. The default attribute mappings work: userPrincipalName → userName, mail → emails[type eq "work"].value, Switch([IsSoftDeleted]…) → active.
  6. Assign users and groups under Users and groups, then set Provisioning Status to On.

Azure provisions in cycles of about 40 minutes. Use Provision on demand to test a single user.

Map groups to roles

In Settings → SSO → SCIM provisioning → Group mapping, map IdP group names (case-insensitive) to roles:

Group (example)Role
Quazzar Adminsorg_admin
Quazzar Operatorsorg_manager
Teachersteacher

A user in several mapped groups gets the highest role. A provisioned user in no mapped group gets the default role (Viewer unless you change it). Changing the mapping re-applies it to all provisioned users. org_owner cannot be mapped. SCIM is the source of truth for provisioned users’ roles: a manual role change in Team is overwritten at the next group change.

On plans below Business

On Community or Pro, the SCIM provisioning card on Settings → SSO carries a Business badge and an Upgrade button, the SCIM panel shows an upgrade card, and the SCIM provisioning switch on Settings → General is locked.

  • Your IdP is refused. Every /scim/v2/* call with a valid token gets 403 Forbidden in the SCIM error format, with a detail that names the plan (SCIM provisioning is not included in this workspace’s plan (Business or above required)…). We use 403 rather than 402 because RFC 7644 has no 402 and because Okta and Entra ID log a 403 with its detail in the provisioning log instead of treating it as a bad credential, as they do with 401. Entra ID may quarantine the app after repeated failures; restart provisioning after you upgrade.
  • Tokens stop working but are kept. The token’s last used time and the workspace’s last sync time are not updated. After an upgrade the same tokens work again, so you don’t need to reconfigure the IdP.
  • Settings stay readable. GET /api/sso/scim/status, /config and /tokens answer with "gated": true and "required_plan": "business".
  • Turning SCIM on is blocked. Creating or rotating a token and changing the default role or the group mapping return 402 upgrade_required ("feature": "scim"). Turning SCIM off (PUT /api/sso/scim/config {"enabled": false}) and revoking tokens still work on any plan.
  • Users and groups the IdP already provisioned stay as they are. Manage them by hand under Team until you upgrade.

What the SCIM server supports

EndpointNotes
GET /scim/v2/ServiceProviderConfig, /ResourceTypes, /SchemasDiscovery
GET /scim/v2/Usersfilter, startIndex, count (max 200), attributes, excludedAttributes
POST /scim/v2/Users, GET/PUT/PATCH/DELETE /scim/v2/Users/{id}PATCH with add / replace / remove (Okta and Azure payload styles)
GET/POST /scim/v2/Groups, GET/PUT/PATCH/DELETE /scim/v2/Groups/{id}Member add / remove / replace, rename

Filters support eq ne co sw ew gt ge lt le pr, and, or, not ( … ), grouping, and value paths such as emails[type eq "work"].value eq "[email protected]". Errors use the SCIM error schema, and responses are application/scim+json. Bulk, sort and ETags are not supported. The enterprise extension (department, employeeNumber, …) is stored and returned as sent.

Every SCIM change, including token and mapping changes, is written to the workspace audit log (scim.user.*, scim.group.*, scim.token.*, scim.config.updated).

Operator setup: Google and GitHub for everyone

The operator of a self-hosted Control Center can offer Google and GitHub buttons to all users by setting:

VariableDescription
CC_PUBLIC_BASE_URLPublic origin of the Control Center, for example https://cp.example.com (used for redirect and SCIM URLs)
CC_SSO_GOOGLE_CLIENT_ID / CC_SSO_GOOGLE_CLIENT_SECRETGoogle OAuth client. Redirect URI: <base>/api/auth/sso/callback/google
CC_SSO_GITHUB_CLIENT_ID / CC_SSO_GITHUB_CLIENT_SECRETGitHub OAuth app. Callback URL: <base>/api/auth/sso/callback/github

These buttons only sign in existing accounts, matched by verified email.

API

MethodPathAuthDescription
GET/api/auth/sso/providers?email=… or ?domain=…public{domain, sso, providers: [{id, kind, label, start_url}]}
GET/api/auth/sso/start/{provider}?next=/pathpublicRedirects to the IdP
GET/api/auth/sso/callback/{provider}publicOAuth / OIDC redirect URI
POST/api/auth/sso/saml/{provider}/acspublicSAML assertion consumer
GET/api/auth/sso/saml/{provider}/metadatapublicSAML SP metadata
POST/api/auth/sso/exchangepublic{code} → same response as POST /api/auth/login
GET/POST/api/sso/login-domainssettings:read / users:manageList / claim sign-in domains
POST/api/sso/login-domains/{domain}/verifyusers:manageCheck the DNS TXT record
DELETE/api/sso/login-domains/{domain}users:manageRemove a domain
GET/api/sso/summarysettings:read[{kind, name, detail, status, users}] for the three cards; the SCIM card adds gated and required_plan below Business
GET/api/sso/scim/statussettings:read{enabled, base_url, token_count, last_sync_at, users_provisioned, groups, gated, required_plan?}
GET/PUT/api/sso/scim/configsettings:read / users:manage{enabled, default_role, group_roles}
GET/POST/api/sso/scim/tokensusers:manageList tokens / create one (plaintext returned once)
POST/api/sso/scim/tokens/{id}/rotateusers:manageRevoke and replace a token
DELETE/api/sso/scim/tokens/{id}users:manageRevoke a token

After a successful IdP round trip the browser is redirected to /login/sso#code=…&next=…. The one-time code sits in the URL fragment, so it never reaches server logs. It is valid for 2 minutes and can be used once.