Configure SSO
Access to the Developer Console runs exclusively through single sign-on (SSO) using an existing OpenID Connect (OIDC) identity provider. Email and password sign-in is not supported.
Persona: Platform operator completing onboarding, working with the identity team that owns the corporate identity provider.
Estimated time: 30 to 60 minutes, most of it spent registering the OIDC client and exchanging values with the identity team.
Overview
Delegating authentication to the corporate identity provider avoids the problems a local credential database accumulates over time: passwords spread across forgotten accounts, no central offboarding signal when someone leaves, no way to enforce multi-factor authentication, and no audit trail tied to the corporate directory. Agent Router has no local password database at all, so the identity provider is the only authority on who may sign in.
Agent Router exposes two web interfaces; both authenticate through the same SSO configuration:
- The Admin Dashboard (
dashboard.<tenant>.tetrate.ai), for platform operators. - The Developer Console (
router.<tenant>.tetrate.ai), for developers.
This guide covers SSO configuration against an existing identity provider. The work falls into two parts:
- Part 1: Agent Router configuration: form expectations, verification, and troubleshooting.
- Part 2: Identity provider configuration: how to register an OIDC client in the identity provider and collect the values needed by the form. Walkthroughs are available for:
When this guide applies
This guide is the right starting point in any of these situations:
| Situation | What it covers |
|---|---|
| First-time SSO configuration on a new tenant | Collecting the Redirect URI, registering an OIDC client, and completing the Configure SSO form |
| Registering Agent Router in a particular identity provider | The per-provider walkthroughs in Part 2 |
| Rotating a client secret | Replacing the credential without interrupting sign-in |
| Switching identity providers | Editing the saved configuration and re-verifying before users are affected |
| Investigating a failed sign-in | The troubleshooting table and the error parameters the identity provider returns |
For the related work of mapping identity-provider claims to Agent Router roles, the most common follow-up to a verified sign-in, see Configure SSO role mapping.
Outcomes
By the end of this guide:
- An OIDC client representing Agent Router is registered in the corporate identity provider, with the tenant's Redirect URI registered against it.
- The Issuer, Client ID, Client Secret, and Discovery URL are recorded and entered in the Configure SSO form.
- At least one administrator email is set, so that the first SSO sign-in produces an account with administrative permissions.
- A sign-in has been completed end to end through the Admin Dashboard or the Developer Console.
- The relationship between this configuration and claim-driven role mapping is clear.
Prerequisites
- Access to the Tetrate onboarding wizard or, once onboarding is complete, the Settings page in the Admin Dashboard.
- Cooperation from whoever owns the corporate identity provider. Most of the values required by the form come from that provider, and the tenant's Redirect URI has to be registered there.
- Permission in the identity provider to create an application registration and read its client secret.
- The email addresses of the people who should hold administrative permissions from the first sign-in onwards. Agent Router has no password fallback, so this decision cannot be deferred.
Process at a glance
- Tetrate onboarding wizard: open the Configure SSO step and click IdP setup guide to reveal the Redirect URI. Copy it.
- Identity provider: register an OIDC client using that Redirect URI. The output is an Issuer, Client ID, and Client Secret.
- Configure SSO form: paste the three values and submit.
- Verify: sign in on the Admin Dashboard or Developer Console sign-in page.
Open the Configure SSO step in the onboarding wizard first. The Redirect URI shown there is tenant-specific, and the IdP side cannot proceed without it.
Part 1: Agent Router configuration
Step 1: obtain the Redirect URI
In the Configure SSO step, click the IdP setup guide button at the top of the form. A panel opens, titled "Configure your SSO provider", with step-by-step instructions and the Redirect URI for the tenant. The format is:
https://auth.<tenant>.tetrate.ai/api/auth/sso/callback/corporate
Use the copy icon to copy the URL.
- The hostname is tenant-specific.
- The trailing path is the same for every customer.
- Most IdPs require the URL to match character-for-character. Any mismatch (scheme, trailing slash, missing path segment) produces a
redirect_uri_mismatcherror at sign-in.
Always copy the URL from the IdP setup guide panel. Don't type it from memory or copy it from this document.
Step 2: register an OIDC client in the identity provider
Use the Redirect URI from Step 1 to register an OIDC client in the identity provider. Walkthroughs for each supported IdP are in Part 2: Identity provider configuration. The output is an Issuer, Client ID, and Client Secret.
Step 3: fill in the Configure SSO form
The Configure SSO step collects the values below.
Issuer (identity provider URL)
The base URL of the OIDC provider. Agent Router uses it to discover other endpoints (authorization, token, userinfo, JWKS) and to validate the iss claim in incoming ID tokens.
Common values:
| IdP | Issuer format |
|---|---|
| Entra ID | https://login.microsoftonline.com/<TENANT_ID> |
https://accounts.google.com | |
| Auth0 | https://<DOMAIN>/ |
| Okta | https://<tenant>.okta.com or https://<tenant>.okta.com/oauth2/default, depending on the authorization server |
| Keycloak | https://<keycloak-host>/realms/<realm> |
The Issuer must match the iss claim the IdP puts in ID tokens exactly. Sign-in failures with no obvious cause usually trace back to an Issuer typo: trailing slash, missing tenant ID, wrong region.
Client ID
The OIDC client ID issued by the IdP.
Client secret
The confidential credential paired with the Client ID. This value is shown only once at creation. Copy it into the form immediately, or store it in a secrets manager.
Discovery URL
The full URL to the IdP's OpenID Connect metadata document:
<Issuer>/.well-known/openid-configuration
Agent Router validates the URL on submit by fetching it and confirming the JSON includes issuer, authorization_endpoint, and token_endpoint. If those are missing or the URL is unreachable, the form returns Invalid OIDC discovery URL.
Scopes
Use openid, profile, email.
Some providers gate group memberships behind an additional scope, which matters for deployments that drive roles from directory groups. Okta is the common case and needs groups added here; see Emit group claims for role mapping. Microsoft Entra ID emits groups and app roles through token configuration instead, with no extra scope.
Admin emails
The email addresses granted Agent Router administrator permissions on first SSO login. This is the bootstrap mechanism for administrative access, and at least one address is always required. Without it, the initial SSO sign-in lands in a standard user account with no administrative privileges, and because Agent Router has no email and password fallback, the result is a permanent lockout from administrative functions.
Add at least one address here before submitting the form. If lockout does occur, the only remedy is to contact Tetrate Support to reset the SSO configuration.
Attribute mapping
Maps the Agent Router email user attribute to the matching claim name in the IdP's ID token. The default is email → email, which works for Google, Auth0, Okta, and Keycloak as registered in this guide. Entra requires an optional claim to be added before it emits email; see the Microsoft Entra ID section.
Step 4: submit the form
Click Configure. Agent Router validates the discovery URL synchronously. A successful response means:
- The discovery document was reachable from Agent Router's auth pod.
- It contained the required OIDC metadata fields.
It does not mean the Client ID or Client Secret are correct. Those are exercised on the first sign-in attempt.
Step 5: verify
After the form accepts the configuration, sign in via the Admin Dashboard or Developer Console sign-in page. Both delegate to the IdP. A successful flow lands back in Agent Router signed in as the IdP user.
If the bounce-back lands at an error page instead of Agent Router, check the URL. Most IdPs include an error query parameter (redirect_uri_mismatch, invalid_client, consent_required) that pinpoints the cause.
If sign-in succeeds but the dashboard shows an account with an empty email or no admin permissions, see the troubleshooting table below.
Confirm the claims in the ID token
Three of the most common SSO problems are invisible from the sign-in screen and obvious in the ID token: an iss value that does not match the configured Issuer, a missing email claim, and a missing groups or roles claim. Reading the token settles which side of the integration is at fault before any configuration is changed. This applies to every provider in Part 2, since all of them are being asked for the same claims.
Agent Router exchanges the authorization code server-side, so the token never passes through the browser. To obtain one, run the same flow by hand against the identity provider:
-
Register a second, throwaway redirect URI on the OIDC client, such as
http://localhost:8080/callback. Every provider in Part 2 accepts more than one. Leave the Tetrate Redirect URI in place. -
Read the endpoints from the discovery document:
curl -s "<Issuer>/.well-known/openid-configuration" \| jq -r '.authorization_endpoint, .token_endpoint' -
Open the authorize URL in a browser and authenticate as a test user. Add
groupsto the scope list when the point of the exercise is to confirm a group claim:<authorization_endpoint>?client_id=<CLIENT_ID>&redirect_uri=http://localhost:8080/callback&response_type=code&scope=openid%20profile%20email&state=check -
The browser lands on a dead
localhostaddress carrying?code=.... Copy the code value out of the address bar. -
Exchange the code for tokens:
curl -s -X POST "<token_endpoint>" \-u "<CLIENT_ID>:<CLIENT_SECRET>" \-d grant_type=authorization_code \-d code="<CODE>" \-d redirect_uri=http://localhost:8080/callback \| jq -r .id_token -
Remove the throwaway redirect URI once the check is finished.
Authorization codes are single-use and expire quickly, so the exchange has to follow the browser step promptly. Where a provider rejects the credentials sent by -u, send them as form fields instead by adding -d client_id=<CLIENT_ID> -d client_secret=<CLIENT_SECRET>. Where the client is configured to require PKCE, the manual flow additionally needs a code_challenge and code_verifier pair; none of the walkthroughs in Part 2 enable PKCE.
Decode the payload locally rather than pasting the token into an online decoder. An ID token identifies a real user and is best treated as a credential:
jq -R 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson' <<<"$ID_TOKEN"
What to look for in the output:
| Claim | Expectation |
|---|---|
iss | Matches the Issuer in the Configure SSO form character-for-character, including the presence or absence of a trailing slash |
aud | Contains the Client ID configured in Agent Router |
email | Present and populated. An absent or differently named claim is the cause behind the empty email row in the troubleshooting table, and is corrected through Attribute Mapping |
groups or roles | Present only where the provider has been configured to emit it. Claim-driven role mapping depends on it, and the name seen here is the one the mapping configuration has to reference |
exp | A Unix timestamp in the future. A token that already looks expired points at clock skew rather than at configuration |
Two providers offer a shortcut that avoids the manual flow. Okta exposes a Token Preview tab on a custom authorization server, which mints a token for a chosen user and client with no browser round-trip, although it is unavailable on the org authorization server this guide recommends. Google decodes and validates a token in a single call to https://oauth2.googleapis.com/tokeninfo?id_token=<ID_TOKEN>, which Google supports for debugging only.
Troubleshooting and common errors
| Symptom | Cause | Fix |
|---|---|---|
| Invalid OIDC discovery URL on form submit | Issuer typo, IdP unreachable from the auth pod, or IdP returns 404 / non-JSON at /.well-known/openid-configuration | Verify the discovery URL is reachable: curl <Issuer>/.well-known/openid-configuration | jq -r '.issuer, .authorization_endpoint, .token_endpoint' |
| Signed in but Agent Router shows an empty email | ID token has no email claim, or claim name is non-standard | Decode the ID token to find the actual claim name, then update Attribute Mapping to point at it, or add email as an emitted claim in the IdP |
| Signed in but no admin permission | Email wasn't in Admin Emails at the time of first SSO sign-in | Contact Tetrate Support to reset SSO and re-run with Admin Emails populated |
For IdP-side errors (redirect_uri_mismatch, invalid_client, callback mismatch), see the IdP's documentation.
Edit the SSO configuration after onboarding
The same fields are editable from the Settings page in the dashboard sidebar (SSO tab) after onboarding completes. The form is identical; only the route differs. SSO cannot be turned off, but the values can be swapped to point at a different IdP.
To rotate the Client Secret without downtime, create a new secret in the IdP, update Client Secret in Agent Router, verify that sign-in works, then delete the old secret in the IdP.
Switch identity providers
Agent Router wires one identity provider at a time. Switching providers replaces the saved configuration; there is no parallel-run mode in which both the outgoing and the incoming provider are accepted, which makes this the most disruptive operation on this surface. The sequence that causes the least disruption:
- Register the OIDC client in the incoming identity provider and collect its Issuer, Client ID, Client Secret, and Discovery URL before anything is changed in Agent Router.
- Where a separate test tenant exists, point that tenant at the new provider first and verify a sign-in there.
- In production, edit Settings → SSO and replace the Issuer, Client ID, Client Secret, and Discovery URL in a single change.
- Verify a sign-in immediately, using the checks in Step 5. Because the change is a replacement rather than an addition, a mistake affects every user at once.
- Coordinate the cutover with the identity team so that the Agent Router-side change and any provider-side change happen close together.
- Announce the change at least one business day in advance for any deployment with a non-trivial number of users. See Communicate with Agent Router users.
Multi-factor authentication
Multi-factor authentication is whatever the identity provider enforces. Agent Router delegates the entire login screen to the provider, so MFA prompts, conditional access policies, and device checks are all applied there and require no configuration in Agent Router.
How SSO interacts with role mapping
SSO authentication settles who is signing in. Role mapping settles a separate question: which Agent Router role that user holds. The two are configured on the same surface but are otherwise independent.
Without role mapping, every user provisioned through SSO lands with the default user role, apart from the addresses listed in Admin Emails, and elevated roles are assigned by hand in the Admin Dashboard. That is workable for a small deployment, but it leaves a synchronisation gap: a change in the directory has no effect on Agent Router until an operator notices and edits the user record.
With role mapping, the claims the identity provider returns (assigned application roles, or group memberships) are translated into Agent Router roles on every login, which makes the directory the source of truth and Agent Router-side role assignment redundant. The complete walkthrough is in Configure SSO role mapping, and it is the right next read once a sign-in has been verified here.
SSO changes in the audit log
A change to the SSO configuration is recorded in the audit log as an sso.configured event, alongside every other administrative change. See Audit Agent Router activity.
That trail is the first place to look when SSO behaviour starts to surprise people. A sudden run of failing sign-ins is usually preceded either by a recent sso.configured event, meaning the configuration itself was changed, or by a change on the identity-provider side that no Agent Router audit log can capture. Ruling out the first narrows the search considerably.
Part 2: identity provider configuration
This section covers how to register an OIDC client in each supported identity provider. Each walkthrough opens with the values it produces, so it can be read as a checklist and handed to the identity team. Only the section for the provider in use needs to be followed.
Microsoft Entra ID
What it produces
| Value | Where it comes from |
|---|---|
| Issuer | App registration → Overview → Endpoints → Authority URL |
| Discovery URL | App registration → Overview → Endpoints → OpenID Connect metadata document |
| Client ID | App registration → Overview → Application (client) ID |
| Client Secret | App registration → Certificates & secrets → New client secret |
One value is registered in Entra: the Redirect URI for the Tetrate tenant.
Prerequisites
- Access to the Microsoft Entra ID instance.
- The Tetrate Redirect URI. Open the IdP setup guide panel in the Configure SSO step to find it.
Step 1: create an app registration
In the Entra admin center, go to App registrations and click + New registration. Fill in the name and complete the form.
Step 2: add the Redirect URI
In the app registration, click Authentication in the left sidebar.
- Click + Add a platform, then choose Web.
- Paste the Redirect URI from the Tetrate onboarding form.
- Click Configure.
Step 3: add optional claims
In the app registration, click Token configuration in the left sidebar, then + Add optional claim.
| Field | Value |
|---|---|
| Token type | ID |
| Claims | Tick email |
Click Add.
Step 4: generate a client secret
In the app registration, click Certificates & secrets in the left sidebar, then + New client secret.
- Add a description, choose an expiry, and click Add.
- Copy the Value column immediately and store it in a secrets manager. Once the page closes, Entra does not reveal it again.
Step 5: collect the Issuer URL and Client ID
In the app registration Overview:
- Click Endpoints in the top toolbar. A drawer opens with several URLs.
- Copy the Authority URL (use as the Tetrate Issuer).
- Copy the OpenID Connect metadata document URL (use as the Tetrate Discovery URL).
- Copy Application (client) ID (use as the Tetrate Client ID).
Done in Entra
The collected values are:
- Issuer, the Authority URL.
- Discovery URL, the OpenID Connect metadata document URL.
- Client ID.
- Client Secret.
Return to Part 1: Agent Router configuration and paste them into the Configure SSO form.
Google Workspace
What it produces
| Value | Where it comes from |
|---|---|
| Issuer | https://accounts.google.com (fixed) |
| Discovery URL | https://accounts.google.com/.well-known/openid-configuration (fixed) |
| Client ID | APIs & Services → Credentials → OAuth client ID |
| Client Secret | APIs & Services → Credentials → OAuth client ID |
Two values are registered in Google: the Authorized redirect URI and the Authorized JavaScript Origins for the Tetrate tenant.
Prerequisites
- A Google Cloud project.
- IAM permission on the project to manage OAuth credentials.
- The Tetrate Redirect URI. Open the IdP setup guide panel in the Configure SSO step to find it.
Step 1: create OAuth credentials
Go to Google Cloud Console → APIs & Services → Credentials and click Create Credentials → OAuth client ID.
Step 2: configure the consent screen
Add:
- App name.
- Support email.
- Scopes:
openid,profile,email.
Step 3: set the Redirect URI
Set the Authorized redirect URI to the Tetrate Redirect URI:
https://auth.<tenant>.tetrate.ai/api/auth/sso/callback/corporate
Step 4: set authorized JavaScript origins
Set Authorized JavaScript Origins to the three Tetrate hostnames for the tenant:
https://auth.<tenant>.tetrate.ai
https://dashboard.<tenant>.tetrate.ai
https://router.<tenant>.tetrate.ai
Step 5: save credentials
Copy:
- Client ID.
- Client Secret.
Done in Google
The collected values are:
- Issuer:
https://accounts.google.com. - Discovery URL:
https://accounts.google.com/.well-known/openid-configuration. - Client ID.
- Client Secret.
Return to Part 1: Agent Router configuration and paste them into the Configure SSO form.
Auth0
For a ground-up Auth0 path (new tenant through credentials ready for onboarding), see Set up Auth0 for evaluation.
What it produces
| Value | Where it comes from |
|---|---|
| Issuer | Build from the Auth0 Domain: https://<DOMAIN>/ (trailing slash) |
| Discovery URL | Build from the Auth0 Domain: https://<DOMAIN>/.well-known/openid-configuration |
| Client ID | Applications → app → Settings |
| Client Secret | Applications → app → Settings |
Three values are registered in Auth0: the Callback URL, Allowed Web Origins, and (optionally) the Logout URL for the Tetrate tenant.
Prerequisites
- An Auth0 tenant.
- A role that allows creating applications and viewing secrets.
- The Tetrate Redirect URI. Open the IdP setup guide panel in the Configure SSO step to find it.
Step 1: create the application
- Go to the Auth0 Dashboard.
- Select Applications.
- Click + Create Application.
- Select Create Manually.
- Enter a recognisable name, such as
Tetrate Agent Router Enterprise. - Select Regular Web Application.
- Click Create.
Step 2: configure application details
On the Settings tab of the new application:
- Under Basic Information, copy the
Domain,Client ID, andClient Secretvalues into a secrets manager or scratch file. The Issuer is built from the Domain in Step 4. - Under Application URIs, set Allowed Callback URLs to the Tetrate Redirect URI:
https://auth.<tenant>.tetrate.ai/api/auth/sso/callback/corporate - Under Application URIs, set Allowed Web Origins to the Tetrate hostnames for the tenant:
https://auth.<tenant>.tetrate.ai
https://dashboard.<tenant>.tetrate.ai
https://router.<tenant>.tetrate.ai
Step 3: set the logout URL (optional)
Still under Application URIs, set Allowed Logout URLs to:
https://auth.<tenant>.tetrate.ai
Click Save.
Step 4: save credentials, if not already done
From the application Settings tab, copy:
- Domain: build the Issuer as
https://<Domain>/(with trailing slash). For example,acme.us.auth0.combecomeshttps://acme.us.auth0.com/. - Client ID.
- Client Secret.
Done in Auth0
The collected values are:
- Issuer:
https://<DOMAIN>/(trailing slash). - Discovery URL:
https://<DOMAIN>/.well-known/openid-configuration. - Client ID.
- Client Secret.
Return to Part 1: Agent Router configuration and paste them into the Configure SSO form.
Okta
One decision shapes everything else in an Okta integration and is best settled before the wizard is opened: which authorization server issues the tokens. It determines the Issuer value, the discovery URL, and where group claims are configured later.
Choose an authorization server
Okta can issue tokens from either of two authorization servers, and they are not interchangeable.
| Org authorization server | Custom authorization server | |
|---|---|---|
| Issuer | https://<tenant>.okta.com | https://<tenant>.okta.com/oauth2/<serverId>, commonly .../oauth2/default |
| Discovery URL | https://<tenant>.okta.com/.well-known/openid-configuration | https://<tenant>.okta.com/oauth2/<serverId>/.well-known/openid-configuration |
| Availability | Present in every Okta org | Requires the API Access Management add-on, which is licensed separately in production orgs |
| Group claims configured on | The application's Sign On tab | The authorization server's Claims tab |
| Custom scopes and claims | Not supported | Supported |
The org authorization server is the right default. It exists in every org, it issues the ID token Agent Router consumes, and it supports the groups claim that role mapping depends on. A custom authorization server is only necessary where the same server also protects the organisation's own APIs, and where API Access Management is already licensed. Deployments that pick .../oauth2/default without that entitlement will find the endpoint absent, which surfaces as an unreachable discovery URL when the Configure SSO form is submitted.
Agent Router validates the ID token only, so the caveats Okta documents around access-token validation on the org authorization server do not apply here.
What it produces
| Value | Where it comes from |
|---|---|
| Issuer | Security → API → Authorization Servers → Issuer URI of the server chosen above |
| Discovery URL | Build from the Issuer: <Issuer>/.well-known/openid-configuration |
| Client ID | Applications → app → General tab → Client Credentials |
| Client Secret | Applications → app → General tab → Client Credentials |
Two values are registered in Okta: the Sign-in redirect URI and, optionally, the Sign-out redirect URI for the Tetrate tenant.
Prerequisites
- An Okta org, and an administrator role that allows creating app integrations and reading client secrets.
- The Tetrate Redirect URI. Open the IdP setup guide panel in the Configure SSO step to find it.
- A decision on the authorization server, as above.
Step 1: create the app integration
In the Okta Admin Console, go to Applications → Applications and click Create App Integration. Where the org offers a choice of wizard, select Classic experience.
- Sign-in method: OIDC - OpenID Connect.
- Application type: Web Application.
- Click Next.
Application type matters more than it appears. A Web Application is a confidential client, which is what allows Okta to issue the client secret Agent Router authenticates with. Selecting a single-page or native application produces a public client with no secret, and the sign-in flow then fails at the token exchange.
Step 2: configure the redirect URIs
Under General Settings:
- App integration name: a recognisable name, such as
Tetrate Agent Router Enterprise. - Grant type: leave Authorization code selected. It is required for this flow and cannot be cleared.
- Sign-in redirect URIs: the Tetrate Redirect URI, exactly as copied from the IdP setup guide panel.
https://auth.<tenant>.tetrate.ai/api/auth/sso/callback/corporate
- Sign-out redirect URIs (optional):
https://auth.<tenant>.tetrate.ai. Absolute URIs only; wildcard subdomains are not accepted in this field.
Leave Allow wildcard in sign-in redirect URI unselected. A single tenant needs exactly one redirect URI, and Okta cautions that subdomain wildcards can allow authorization codes to be sent to an attacker-controlled page.
The Trusted Origins section of the wizard, with its optional Base URIs field, governs cross-origin browser calls to the Okta API. It is not required for the server-side authorization code exchange Agent Router performs.
Step 3: set client authentication
In Client Credentials, confirm Client authentication is set to Client secret rather than Public key / Private key. Agent Router authenticates to the token endpoint with a client secret, and there is no field in the Configure SSO form for a private key. Proof Key for Code Exchange (PKCE) may be left at its default.
Step 4: set controlled access
The Assignments section governs who may sign in. Under Controlled access, either allow everyone in the organisation, or select Limit access to selected groups and name the groups that should reach Agent Router. Click Save.
Okta enforces this before Agent Router ever sees the user, so an unassigned user is refused at the identity provider no matter how Agent Router is configured. Assignment is also the mechanism for restricting Agent Router to a pilot group during a phased rollout. Choosing Skip group assignment for now leaves the application with no one assigned, and every sign-in attempt then fails.
Step 5: collect the Client ID and Client Secret
On the application's General tab, under Client Credentials, copy:
- Client ID.
- Client secret. Copy it into the Configure SSO form immediately or store it in a secrets manager. Okta reveals the value once.
Step 6: confirm the Issuer URL
Go to Security → API → Authorization Servers and copy the Issuer URI of the server chosen in the first step. Rather than transcribing it, confirm the canonical value by reading the discovery document, and use whatever the issuer field returns:
curl -s "<Issuer>/.well-known/openid-configuration" | jq '.issuer, .authorization_endpoint, .token_endpoint'
An Issuer mismatch is the most common cause of an Okta sign-in that fails with no informative error, and Okta issuers have several ways of looking almost right:
- No trailing slash. Neither form of Okta issuer ends in
/, unlike Auth0. - The domain suffix follows the cell the org lives in:
okta.com,okta-emea.comfor EMEA cells, oroktapreview.comfor preview and sandbox orgs. A value copied from a sandbox runbook will not work against production. - Where the org uses a custom domain, an
issuer_modesetting decides whether tokens carry the Okta org URL or the custom domain. The configured Issuer has to match whichever one the tokens actually assert. Disabling a custom domain resetsissuer_modeback to the org URL, which changes theissvalue and breaks sign-in with no change on the Agent Router side.
The openid, profile, and email scopes are standard, and Okta emits a standard email claim in the ID token, so the default email → email attribute mapping needs no change.
Done in Okta
The collected values are:
- Issuer, the Issuer URI of the authorization server.
- Discovery URL, the Issuer with
/.well-known/openid-configurationappended. - Client ID.
- Client Secret.
Return to Part 1: Agent Router configuration and paste them into the Configure SSO form.
Emit group claims for role mapping
Group claims are only needed where roles, rate limits, or budgets are driven from directory membership. Base sign-in works without them.
Okta does not emit group memberships by default. On the org authorization server, the claim is configured on the application rather than centrally:
- In the Okta Admin Console, go to Applications → Applications and select the application created above.
- Open the Sign On tab and click Edit in the OpenID Connect ID Token section.
- Set Group claim type to Filter.
- Under Group claims filter, leave the claim name as
groups, or enter it if the field is empty. - Set the filter to Matches regex with a value of
.*to return every group the user belongs to. A narrower regex is preferable in a large org, so that the token carries only the groups Agent Router maps. - Click Save, then return to the applications list, open the More menu, and choose Refresh Application Data.
On a custom authorization server the equivalent is configured under Security → API, on the chosen server's Claims tab, which also allows the claim in access tokens. Okta's groups claim guide covers both paths, including the expression syntax needed for groups sourced outside Okta, such as those synchronised from Active Directory.
Two details decide whether the claim actually arrives:
- The
groupsscope has to be requested. Okta returns the claim only whengroupsis among the requested scopes, so the Scopes field in the Configure SSO form needsopenid, profile, email, groupsrather than the default three. - The flow has to return a full ID token. Okta issues what it calls a thin ID token, carrying base claims only and omitting groups, for implicit and several other flows. The authorization code flow Agent Router uses returns the full token, so the claim is present once the two points above are satisfied.
At the mapping layer Agent Router draws no distinction between providers: it reads the group values it receives and matches them against the configured rules, so Okta groups drive role assignment, rate limits, and budgets exactly as Entra ID groups do. The claim-to-role mechanics are in Configure SSO role mapping, and the end-to-end treatment of group-to-business-function mapping, written against Entra ID but applicable to Okta groups unchanged, is in Map Entra ID groups to business functions.
Rotate an Okta client secret
Okta supports two concurrent client secrets on an application, both active at once, which is what makes the rotation sequence in Edit the SSO configuration after onboarding possible without a sign-in outage:
- On the General tab, under Client Credentials, click Generate new secret. Both secrets are now valid.
- Update Client Secret in Agent Router with the new value and confirm a sign-in succeeds.
- Set the old secret's status to Inactive in Okta.
- Delete the inactive secret. The limit is two, so the old one has to be removed before the next rotation.
Okta-specific troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Okta reports the user is not assigned to the application | The signing-in user is not in the application's Assignments, directly or through a group | Assign the user or their group under Assignments, or widen Controlled access |
redirect_uri_mismatch at sign-in | Sign-in redirect URIs does not match the Tetrate Redirect URI character-for-character | Re-copy the value from the IdP setup guide panel; check scheme, trailing slash, and the full /api/auth/sso/callback/corporate path |
invalid_client at the token exchange | Wrong Client ID or Client Secret, or the app was created as a public client | Re-copy both values from Client Credentials; confirm the app is a Web Application with Client authentication set to Client secret |
| Sign-in succeeds but no groups reach Agent Router | The groups scope is not requested, or no group claim is configured on the app | Add groups to the Scopes field and configure the claim as described above, then decode the ID token to confirm the claim now arrives |
| Sign-in worked previously and now fails with no configuration change | A custom domain was enabled or disabled in Okta, changing the iss value the tokens assert | Re-read the discovery document and update the Issuer to match |
Other OIDC providers (Keycloak, Ping, and custom)
The flow matches the supported IdPs above; only the IdP UI changes. From the IdP, register a Web application, set the Redirect URI to the value Agent Router's form supplies, enable the openid, profile, email scopes, generate a client secret, and collect Issuer, Client ID, and Client Secret.
For the Issuer, find the IdP's OIDC discovery URL and check that it returns valid JSON with issuer, authorization_endpoint, and token_endpoint:
curl -s "<Issuer>/.well-known/openid-configuration" \
| jq '.issuer, .authorization_endpoint, .token_endpoint'
The value .issuer returns is what goes into the Agent Router Issuer field. Even small differences (trailing slash, version path) break sign-in.
What to do next
- SSO role mapping. Map identity-provider claims to Agent Router roles so that directory changes propagate without manual intervention. See Configure SSO role mapping.
- Map Entra ID groups to business functions. Drive roles, rate limits, and budgets from directory group membership. See Map Entra ID groups to business functions.
- Audit Agent Router activity. The configuration change made here is one of the administrative events the audit log records. See Audit Agent Router activity.
- Run multiple Agent Router instances. SSO is configured per instance, and the multi-instance considerations are non-trivial. See Run multiple Agent Router instances.
Where to go next
Console quickstart
Issue an API key and confirm a first routed request once SSO is working and the gateway is reachable.
Admin Dashboard quickstart
Review models, providers, users, and usage analytics from the management plane.
SSO role mapping (optional)
After base SSO is verified, map OIDC roles and groups to Agent Router roles.
Self-hosted path
Where SSO was deferred during onboarding, this is the next step before developer handoff. The full self-hosted sequence.