Single sign-on
Console sign-in through your identity provider.
With single sign-on (SSO), your members sign in to the RouterPlus console through your identity provider. RouterPlus supports OpenID Connect (OIDC) and SAML 2.0, with Okta, Microsoft Entra ID and Google Workspace.
An organization can have several connections. Each connection signs in the emails of its domains. For example, acme.com signs in through Okta and acme.co.uk through Entra ID.
- Members sign in at
https://demo.routerplus.com/ssowith their work email. RouterPlus sends them to the connection for that domain. - The sign-in link for one connection is
https://demo.routerplus.com/sso/start?connection=<connection id>. - Email links and the normal sign-in page continue to work.
In the console, open Team > Single sign-on.
Set up a connection
- 01Create the application in your identity provider. See the sections below.
- 02Create the connection with a management key:
POST https://demo-api.routerplus.com/v1/sso/connections. - 03Add the DNS TXT record that the answer shows for each domain.
- 04Verify the domains:
POST https://demo-api.routerplus.com/v1/sso/connections/<id>/verify-domains. - 05Add your members to the organization, or turn on just-in-time provisioning.
A connection signs in no one until you verify its domain.
The URLs your identity provider needs
| Use | URL |
|---|---|
| OIDC redirect URI (sign-in redirect URI) | https://demo.routerplus.com/sso/oidc/callback |
| SAML assertion consumer service (ACS, reply URL) | https://demo.routerplus.com/sso/saml/acs |
| SAML audience (entity id of RouterPlus) | the connection's sp_entity_id |
| SAML metadata of RouterPlus | https://demo.routerplus.com/sso/saml/metadata?connection=<connection id> |
Create a connection
OIDC:
curl https://dev2-api.routerplus.com/v1/sso/connections \
-H "Authorization: Bearer $ROUTERPLUS_MANAGEMENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "oidc",
"name": "Okta",
"email_domains": ["acme.com"],
"issuer": "https://acme.okta.com",
"client_id": "0oa1b2c3d4",
"client_secret": "...",
"default_role": "viewer",
"jit_provisioning": false
}'SAML:
curl https://dev2-api.routerplus.com/v1/sso/connections \
-H "Authorization: Bearer $ROUTERPLUS_MANAGEMENT_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "saml",
"name": "Entra ID",
"email_domains": ["acme.com"],
"idp_entity_id": "https://sts.windows.net/<tenant id>/",
"idp_sso_url": "https://login.microsoftonline.com/<tenant id>/saml2",
"idp_certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
}'The response is 201, with the connection in data.
Fields
| Field | Kind | Meaning |
|---|---|---|
kind | both | oidc or saml. You cannot change it later. |
name | both | A label, 1 to 100 characters. |
email_domains | both | 1 to 50 domains. The connection signs in only emails at these domains. |
enabled | both | false stops all sign-ins through the connection. Default true. |
default_role | both | viewer or admin. The role a member gets from just-in-time provisioning. Default viewer. |
jit_provisioning | both | true adds a new email to the organization at its first sign-in. Default false. |
issuer | OIDC | The issuer URL of your identity provider, https only. RouterPlus reads <issuer>/.well-known/openid-configuration. |
client_id | OIDC | The client id of the application. |
client_secret | OIDC | The client secret. Leave it out for a public client with PKCE only. |
allowed_tenant_ids | OIDC | Up to 50 Entra ID tenant ids that can sign in. See Tenant filtering. |
idp_entity_id | SAML | The issuer (entity id) of your identity provider. |
idp_sso_url | SAML | The single sign-on URL of your identity provider, https only. |
idp_certificate | SAML | The signing certificate of your identity provider, in PEM or as bare base64. RSA keys only. |
sp_entity_id | SAML | The audience that your identity provider puts in the assertion. Default urn:routerplus:sso:<connection id>. |
RouterPlus stores the client secret encrypted and never returns it. A connection with a secret shows "client_secret": "__secret__".
Routes
All routes take a management key. They also work under /api/v1.
| Route | What it does |
|---|---|
GET /v1/sso/connections | Lists your organization's connections. |
POST /v1/sso/connections | Creates a connection. |
GET /v1/sso/connections/<id> | Shows one connection. |
PATCH /v1/sso/connections/<id> | Changes the fields you send. Send "client_secret": null to remove the secret. |
DELETE /v1/sso/connections/<id> | Deletes the connection. |
POST /v1/sso/connections/<id>/verify-domains | Looks up the DNS records and marks the domains verified. |
RouterPlus writes every change to the audit log (GET /v1/audit).
Verify your domains
Each domain in the response has a verification object:
{
"domain": "acme.com",
"verified": false,
"verification": { "type": "TXT", "name": "_routerplus-sso.acme.com", "value": "routerplus-sso=4f1c..." }
}- 01At your DNS provider, add a TXT record with that name and value.
- 02Call
verify-domains. The response lists each domain withverified. A domain that fails also has areason. - 03If a domain fails, call
verify-domainsagain after your DNS change propagates.
- In your organization, a domain belongs to one connection.
- A verified domain belongs to one organization. No other organization can verify or add it.
- A domain stays verified when you change the connection's other fields. A domain that you remove loses its verification.
Okta
OIDC:
- 01In the Okta admin console, open Applications, then Create App Integration.
- 02Select OIDC - OpenID Connect and Web Application.
- 03Set the sign-in redirect URI to
https://demo.routerplus.com/sso/oidc/callback. - 04Assign the application to your people or groups.
- 05Copy the client id and client secret. The issuer is your Okta domain, for example
https://acme.okta.com. With a custom authorization server, the issuer is that server's URL, for examplehttps://acme.okta.com/oauth2/default.
SAML:
- 01Create an app integration and select SAML 2.0.
- 02Set Single sign-on URL to
https://demo.routerplus.com/sso/saml/acs. - 03Set Audience URI (SP Entity ID) to the connection's
sp_entity_id. - 04Set Name ID format to
EmailAddressand Application username toEmail. - 05Open View SAML setup instructions. Copy the identity provider issuer, the single sign-on URL and the X.509 certificate.
To use the default sp_entity_id, create the connection first. Then add the Okta fields with PATCH.
Microsoft Entra ID
OIDC:
- 01In the Entra admin center, open App registrations, then New registration.
- 02Add a Web redirect URI:
https://demo.routerplus.com/sso/oidc/callback. - 03Under Certificates & secrets, create a client secret.
- 04Under Token configuration, add the optional claim
emailto the ID token. - 05The issuer for a single-tenant app is
https://login.microsoftonline.com/<tenant id>/v2.0.
Entra ID does not send email_verified. Make sure that each user's email attribute holds their real work email.
SAML:
- 01Open Enterprise applications, then New application, then Create your own application.
- 02Under Single sign-on, select SAML.
- 03Set Identifier (Entity ID) to the connection's
sp_entity_id. - 04Set Reply URL (Assertion Consumer Service URL) to
https://demo.routerplus.com/sso/saml/acs. - 05Download Certificate (Base64). Copy Login URL (the
idp_sso_url) and Microsoft Entra Identifier (theidp_entity_id).
RouterPlus reads the email from the NameID when it is an email. Otherwise it reads the emailaddress claim.
Google Workspace
OIDC:
- 01In Google Cloud console, open APIs & Services, then Credentials.
- 02Create an OAuth client ID of type Web application.
- 03Add the authorized redirect URI
https://demo.routerplus.com/sso/oidc/callback. - 04The issuer is
https://accounts.google.com.
Set the OAuth consent screen to Internal. Then only your Workspace accounts can sign in.
SAML:
- 01In the Google Admin console, open Apps, then Web and mobile apps, then Add custom SAML app.
- 02Copy the SSO URL, the entity id and the certificate.
- 03Set ACS URL to
https://demo.routerplus.com/sso/saml/acsand Entity ID to the connection'ssp_entity_id. - 04Set Name ID format to
EMAILand Name ID to Primary email. - 05Turn the app on for your organizational units.
Tenant filtering
A connection signs in a person only when both conditions are true:
- The email's domain is one of the connection's verified
email_domains. - For Entra ID with
allowed_tenant_idsset, thetidclaim is in that list.
A multi-tenant Entra ID app uses the issuer https://login.microsoftonline.com/organizations/v2.0 or /common/v2.0. Any Entra tenant can sign in to such an app, and a tenant admin can set any email on a user. Thus a connection with a multi-tenant issuer needs allowed_tenant_ids. Without the list, the connection refuses every sign-in.
Just-in-time provisioning
jit_provisioningoff: only existing members sign in. Add members in the console or with SCIM.jit_provisioningon: a person with an email at a verified domain joins the organization at the first sign-in, withdefault_role(vieweroradmin).
SSO never makes an owner. A member that an admin turned off stays off.
What a sign-in checks
OIDC:
- Authorization code flow with PKCE (
S256),stateandnonce. - The ID token signature, against the identity provider's published keys.
iss,aud(yourclient_id),exp,nbf,iatandnonce.email_verifiedmust betruewhen the claim is present.
SAML:
- RouterPlus sends an AuthnRequest with the HTTP-Redirect binding. It reads the response with the HTTP-POST binding.
- The response or the assertion must be signed with RSA-SHA256 and exclusive canonicalization. Every signature in the response must verify with
idp_certificate. Destination,Recipient,Audience,InResponseTo,NotBeforeandNotOnOrAftermust match.- RouterPlus accepts an assertion one time.
- RouterPlus refuses encrypted assertions, and XML with a DOCTYPE or entity declarations.
The sign-in must finish in the browser that started it, within 10 minutes. Sign-ins start only from RouterPlus. RouterPlus refuses an unsolicited (IdP-initiated) SAML response.
Errors
The sign-in page shows the reason.
| Message | Fix |
|---|---|
| Single sign-on is not set up for this email domain | Add the domain to a connection, verify it and set enabled to true. |
This connection does not sign in emails at <domain> | Add the domain to the connection and verify it. |
| You are not a member of this organization | Add the person as a member, or turn on jit_provisioning. |
| Your account in this organization is turned off | An admin turned the member off. Turn the member on again. |
| The ID token has no email claim | Add the email scope or the email optional claim. |
| Your identity provider has not verified this email address | Verify the email in the identity provider. |
| Your Entra ID tenant is not allowed | Add the tenant id to allowed_tenant_ids. |
| Set allowed tenant ids on the connection | A multi-tenant Entra ID issuer needs allowed_tenant_ids. |
| The identity provider did not complete the sign-in | Check client_id, client_secret and the redirect URI. |
| The SAML response was refused: ... audience ... | Set the audience in the identity provider to sp_entity_id. |
| The SAML response was refused: ... signature ... | Upload the identity provider's current signing certificate. |
| The SAML response was refused: ... encrypted assertions ... | Turn assertion encryption off. |
| This sign-in request has expired or was already used | Start the sign-in again. |
| This sign-in was started in another browser | Start the sign-in again in this browser. |
For agents: /docs/sso.md and /llms.txt