Skip to main content

Enterprise SSO enrollment

Users self-enroll with their corporate identity; offboarding is revocation.

Set up SSO

Everything happens in the Anyray console (:3000) under Users → Identity (admin key required). The Identity card holds three tiles: Single sign-on (SSO), Directory sync (SCIM), and SSO configuration.

1
Connect your IdP
In the Identity card, click the Single sign-on (SSO) tile to open the WorkOS Admin Portal and follow its steps for your provider.
2
Configure SSO
Click the SSO configuration tile and set allowed email domains, session length, and group mappings (below).
3
Optional: directory sync
Click the Directory sync (SCIM) tile for push-based, hands-off deprovisioning.
note

The Single sign-on (SSO) tile shows Connected only once your IdP connection is actually active in WorkOS. Opening the Admin Portal starts the setup but doesn't complete it — until you finish the provider's steps, the tile stays Off and the standard invite / MDM enrollment paths remain available.

SSO configuration

SettingWhat it does
Allowed email domainsOnly IdP-verified emails in these domains may enroll (empty = any verified email).
Group → team mappingMap an IdP group to an Anyray team (spend attribution); first match wins, else the default team. At login the user picks from every mapped team plus the default.
Group → role mappingMap an IdP group to a console role; first match wins, else viewer.
Default teamOptional. The team a user lands on when no mapped group matches.
Session length (hours)How long a minted ark_ key lasts. Default 30 days; minimum 1 hour, maximum 365 days (8760). A key in active use renews — only idle keys lapse. Console operator sign-ins derive from this value but stay capped at 30 days regardless.
Re-enrollment window (hours)Optional. How long a device can go unused before the person must sign in again through the IdP in the browser. A machine in regular use renews its enrollment certificate silently and never reaches it. Empty = 30 days; only takes effect when set longer than the session length. Needs gateway v1.10.105+ (older gateways fall back to the session length).

Roles are console permissions only. owner is a fifth, break-glass role held solely by the admin key (ANYRAY_ADMIN_TOKEN) — it passes every check and is never granted through SSO.

Console roles — what each can do

A user's console role sets what they can do, from read-only dashboards up to managing SSO and keys. auditor and operator each build on viewer; security_admin includes both.

RoleCan do
viewerRead-only — dashboards, spend, trace metadata. Fallback for any unmapped user.
auditorviewer, plus read the audit log.
operatorviewer, plus change routing, model aliases, user caps, and run the playground. No audit-log access.
security_adminoperator and auditor, plus manage SSO/IdP config, provider & client keys, content settings, the optimizer, and updates.

Assigning roles. Under Users → Identity → SSO configuration, set Group → role mapping — one group=role per line. First matching group wins; unmapped falls back to viewer.

Group → role mapping
platform-admins=security_admin
devops=operator
The account owner is set up automatically

On first connect, the account owner gets security_admin so someone can always administer the console, then maps the rest of your groups. To assign by exact person instead of group, use email → role assignment in the admin API.

Role mappings read your IdP's group claims

Group → role and Group → team resolve from the groups your IdP asserts at sign-in. If your provider only sends groups over SCIM directory sync (not in the SSO assertion), map by email instead, or add the group attribute to your WorkOS connection. Changes take effect on each user's next sign-in.

What configuring SSO enforces

Once your IdP connection is active, standalone enrollment stops working and identity is server-verified — enrollment fails closed if the policy can't be read, and client headers can't claim SSO or replace the bound identity. In detail, the Billing backend reads the tenant's SSO config before minting or redeeming enrollment credentials, and:

  • Minting a regular enl_… link or enp_… provisioning token returns 409. Rotating an existing provisioning token also returns 409; listing and revocation remain available.
  • Previously issued enl_… links and both email- and machine-mode enp_… tokens return sso_required; they never sign a standalone certificate.
  • Certificates issued before you connected the IdP stop rolling forward, so they lapse at their own expiry and that developer signs in through the IdP instead. Nothing is cut off at the moment you connect — an existing certificate stays valid to its original expiry — but enforcement does reach everyone who enrolled earlier, rather than only new developers.
  • MDM distributes the SSO handoff with no embedded credential. Each developer authenticates through the IdP on first use. A genuinely non-human workload uses a separately managed service key.
  • SSO status and identity come from durable server-side records and signed bindings.

No policy response contains a raw token, prompt, or response.

Enroll a developer

1
Copy the enrollment command

Once your IdP connection is active, click Add user on the Users page, choose SSO enrollment, and copy the command under Share this command. The link is organization-wide — safe to share in Slack, not tied to one person.

2
Run it on the developer's machine

It opens the IdP sign-in, mints a personal ark_… key bound to the verified identity, and configures every supported tool it finds. On first login, Anyray creates the membership and applies the configured role, team, session length, and default budget.

macOS / Linux
curl -fsSL https://app.anyray.ai/connect.sh | sh -s -- --sso https://app.anyray.ai/sso/<tenantId> --yes

The installer downloads a standalone binary to a persistent path (~/.anyray/bin), so the retrieval MCP and hooks it registers keep working. Prefer npm? npx anyray-connect@latest --sso https://app.anyray.ai/sso/<tenantId> --yes works too, but installs to a temporary path — some retrieval-based optimizations stay off until you install durably.

3
Sign in through your IdP

Connect prints a short code and opens the browser; the user signs in. The code and URL are always printed, so the flow works over SSH or headless. A stale or disabled link returns 404.

Enrollment is complete

The terminal reports the verified identity, each detected tool's result, and a final file count. The personal key and refresh credential are stored locally with owner-only permissions.

Gateway-first login compatibility path

anyray-connect login --gateway https://<your-anyray-gateway> remains available for existing workflows. It signs in, lets the user choose an eligible team, and configures the Claude Code subscription lane. Run a normal anyray-connect apply afterward to configure every other detected tool. New onboarding should use the SSO enrollment command above so enrollment and the full apply happen in one command.

Provision users directly with SCIM

Use the gateway's SCIM 2.0 server when Okta, Microsoft Entra ID, or another IdP should own the user and group lifecycle directly, instead of WorkOS self-enrollment. The base URL is https://<your-anyray-gateway>/scim/v2.

Set up inbound SCIM
1
Choose a bearer token

Create a high-entropy static token in your secrets manager. The IdP sends it on every SCIM request. Anyray stores only its SHA-256 hash in the shared gateway database.

2
Configure the gateway

Set the bearer, the IdP group that grants the Anyray admin role, and any group-to-team mappings. The admin token below is the gateway's existing break-glass credential.

Configure inbound SCIM
curl -X PUT https://<your-anyray-gateway>/admin/scim/settings \
-H "Authorization: Bearer $ANYRAY_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bearerToken": "synthetic-scim-bearer-token-replace-me-0001",
"adminGroup": "Anyray Admins",
"groupTeamMap": {
"Platform Engineering": "platform",
"Anyray Admins": "platform"
}
}'
3
Connect the IdP

In the IdP, set the SCIM base URL above and use the same static bearer. Enable user and group pushes. Anyray supports discovery, Users and Groups CRUD, paging, userName eq "…" filters, user activation, and group membership patches.

4
Verify provisioning

Assign a synthetic test user and mapped group in the IdP. The user appears in the Users roster with source scim, type person or service, the mapped team, and the configured role.

GET /admin/scim/settings returns whether SCIM is configured plus the admin-group and team map. It never returns the bearer or its hash. Updating mappings without bearerToken keeps the current token; include a new bearer to rotate it.

Groups can create missing users

If a group push references a user that hasn't arrived yet, include the member's email in its display field. Anyray creates the identity first, then resolves its team and admin role from the verified group payload.

Deprovision

  • Direct gateway SCIMactive:false or DELETE /scim/v2/Users/:id writes a durable inactive identity. Every replica checks it during client-key verification, so existing keys stop working immediately. Fails closed if the identity store can't be read.
  • Directory Sync — removing the user in your IdP fires a webhook that revokes them automatically.
  • Manual revokeUsers → Identity → SSO configuration → Offboard a person, revoke by email. Re-minting and re-sliding stop within ~15 min. Reinstate with one click.
  • Key expiry (backstop) — a revoked key still lapses within the session length, and revocation blocks re-mint.

Keys auto-renew while in use, so active developers are never interrupted (Claude Code refreshes a lapsed key at session start). Renewal re-mints from the local enrollment certificate — it never revives a revoked key, and a leaked key alone can't renew.

The enrollment certificate itself also rolls forward on its own while the device is in use, which is why an active developer never gets sent back to the browser. That renewal is checked against the same revocation list, so revoking someone stops it too: their current key lapses within the session length, and the certificate behind it stops renewing at the same moment.

Revocation is the offboarding control — not certificate expiry

Because certificates renew, you cannot rely on one aging out to remove access. Deprovision through your IdP (Directory Sync), SCIM, or Offboard a person. Any of those cuts the device off; doing nothing leaves it working.