Identity providers
Connect the identity provider your company already uses, such as Okta or Microsoft Entra ID, to your EACH 1 account. People then sign in with the company login, join and leave with your directory, and can pass their own groups to agents. This is workforce identity federation, and it is optional. Enroll an agent first: Your first governed agent, by API needs no identity provider.
What it gives you
- Sign-in with the company login (SSO). People sign in through your identity provider, over OIDC or SAML 2.0, with no Eniyan password.
- People added and removed for you (SCIM). Your identity provider creates members and deactivates leavers. A leaver's operator credentials are revoked in the same step.
- Agent permissions that follow a person. A member can delegate a group they hold to an agent. When they lose the group, the agent loses the permission, with no call from you.
What it does not do:
- Agents never sign in through the identity provider. An agent presents its own Eniyan credential.
- It does not turn password sign-in off. A member who has a password keeps it. An account created by SSO or SCIM has no password and signs in through the identity provider only.
Connect sign-in
In the dashboard, open People and choose the Identity providers tab. Only an admin can change the connection. Other members see a notice instead of the form.
- In your identity provider, create an application for Eniyan: an OIDC web application, or a SAML 2.0 application.
- Copy the values under 1. Add these to your IdP app into it. OIDC needs the Sign-in redirect URI and the Allowed scopes (openid email profile). SAML needs the SP Entity ID (Audience) and the ACS URL (Single sign-on URL).
- Under 2. Enter your IdP details, choose the Provider and the Protocol. The provider is a label for the audit record and the field hints. It changes no behavior.
- For OIDC (OpenID Connect), enter the Issuer URL, Client ID and Client secret. For SAML 2.0, enter the IdP Entity ID (Issuer), the IdP Single Sign-On URL and the X.509 signing certificate.
- Optionally set Allowed email domain. Only addresses at that domain may then sign in through SSO.
- Press Connect SSO. The page then reads Connected. For an OIDC connection, Test fetches your provider's discovery document. It does not contact a SAML provider.
The client secret is stored encrypted and is never shown again. Leave the field blank on a later save to keep the stored one. A blank SAML certificate field keeps the stored certificate in the same way. Every change to the connection is emailed to all of your admins and written to the audit log: connecting, updating, disconnecting and generating a SCIM token.
How members sign in. On the sign-in page, a member presses Sign in with SSO, types your organization's slug under Organization, and presses Continue with SSO. The slug is the short name shown under the organization name at sign-up. GET /v1/auth/me returns it as org_slug.
Sign-in starts at Eniyan. GET /v1/auth/sso/{org_slug}/start sends the browser to your identity provider, so a bookmark or an app tile can point at that address. OIDC uses the authorization code flow with PKCE. SAML uses a request from Eniyan and a signed response posted back. A sign-in that starts at the identity provider is refused.
What a first sign-in creates. A person with no Eniyan account gets one on their first sign-in, with the Developer role and no password. An admin can change the role on the People and roles tab. A person who already has an account is matched by email and keeps their role and password. With OIDC, linking a password account needs your provider to mark the email verified (email_verified). Without it, that sign-in is refused.
An SSO sign-in satisfies an organization's two-step verification requirement. A member who turned two-step verification on for their own account is still asked for their code.
Add and remove people (SCIM)
SCIM (System for Cross-domain Identity Management) lets your identity provider create and deactivate members for you. Save the connection first, then set up provisioning in your identity provider with two values from the same page.
- SCIM 2.0 base URL. Copy it from the page. It ends in /scim/v2 and has no /v1 prefix.
- SCIM bearer token. Under 3. Provisioning & checks, press Generate. The token appears once, as SCIM token (shown once). Copy it into your identity provider then: Eniyan keeps only a hash of it. Regenerate issues a new token and the old one stops working.
What each call does:
- Create. POST /scim/v2/Users creates a member with the Developer role and no password. Eniyan matches on externalId, then on userName, which is the email. A member who already exists is kept, and a deactivated one is reactivated unless the request says inactive.
- Deactivate. DELETE /scim/v2/Users/{id}, or active: false sent by PATCH or PUT, deactivates the member. Nothing is deleted. Their sign-in stops and every operator credential they hold is revoked.
- Their agents. Each agent the leaver operated passes to a co-operator, or is suspended until an admin adopts it. See What happens when an operator departs. Reactivating the member restores sign-in only.
- Group Push. /scim/v2/Groups accepts creating, renaming and deleting groups and changing their members. Each change updates the group list of the members it names. The group's display name is what a member can later delegate.
- What is supported. PATCH, and the user filter userName eq. Bulk requests, sorting, ETags and password changes are not supported.
Give agents permissions from groups
A member's groups come from your identity provider: from the groups claim at SSO sign-in, and from SCIM Group Push. Each member sees their own list under People, on the Me tab, as My Entitlements.
To give an agent one of your groups, open the agent's page and find the Entitlement Delegations card. Choose the groups under Delegate your entitlements and confirm. The group's name, exactly as your identity provider sends it, becomes a scope the agent is permitted.
- You can delegate only a group you hold now. Any member can delegate their own groups, and each delegation records who made it.
- The delegator or an admin can remove a delegation with Revoke.
- A delegation counts only while the delegator is active and still holds the group. The card marks each one Live or Lapsed.
- When a Group Push or the member's next sign-in drops the group, or the person is deprovisioned, the delegation lapses. The agent loses the scope at its next check, which can be up to a minute later.
- An agent with any delegation is held to its declared scopes. A lapsed delegation narrows what the agent may do, to nothing if it was the only source. It never widens it.
The same set decides the agent's access tokens: a token carries only the scopes it asked for that the agent is permitted. The agent's Authority view names each delegated scope as Delegated by the member. For every source of an agent's permitted scopes, see Agent RBAC. Role bindings can also match on an operator's groups: see Role bindings.
No identity provider: the entitlement feed
If your entitlements live in your own platform and not in identity provider groups, your platform can send Eniyan who holds what. Each member then sees that list as My Entitlements and delegates from it exactly as described above. The feed and an identity provider are never on together: turning the feed on is refused while SSO is connected (409 IDP_CONNECTED), and connecting SSO is refused while the feed is on (409 ENTITLEMENT_FEED_ACTIVE).
An admin turns it on under Settings, on the Identity providers page, in the Entitlement feed card. The token is shown once. Your platform sends it as a Bearer header on PUT /v1/entitlement-feed/members with a body of {"members": [{"email": "...", "entitlements": ["..."]}]}. Your organization API key is refused on this route.
- The list you send for a member replaces that member's list. Members you leave out are not changed, and sending the same thing twice changes nothing.
- The feed adds, activates and removes nobody. An email that is not a member of your organization comes back under skipped.
- Send "dry_run": true to get the same answer, including each member's added and removed, with nothing written.
- One call carries up to 500 members, 200 entitlements each, 255 characters per name. A call over a limit, or one that names a member twice, is refused whole.
- An entitlement's name becomes the scope an agent is permitted, so it must match the scope your platform asks Eniyan to check.
- Taking an entitlement away removes it from that member's agents at their next check. Sending it again restores it with no new delegation.
- Nothing expires: the last sync stays in force, also after the feed is turned off. The card shows when the last sync arrived.
- Every sync that changes something is in your audit log with each member changed and what was added and removed. Generating a token and turning the feed off email every admin. If a token leaks, generate a new one (the old one stops at once) and re-send the members the audit log shows were changed.
Disconnecting
Disconnect, under Disconnect SSO, asks you to confirm. Before you can, the page shows What this connection feeds. It counts the members who sign in or are provisioned through it, and how many of them have no password. It also counts the groups pushed by provisioning, the delegations in force, and the agents holding a scope that rests only on those groups. A count that could not be read says unknown, never zero. The preview is GET /v1/idp/connection/impact, which changes nothing.
Disconnecting stops single sign-on and provisioning, and it removes nothing. Members' groups freeze at their last sync: existing delegations stay in force and stop following the identity provider. A group change or a leaver there no longer reaches Eniyan, so deactivate a leaver in the dashboard while you are disconnected.
Members with a password are unaffected. Members with no password cannot sign in until the connection is back. Saving the connection again turns it on again.
Limits and notes
- One connection per organization, on one protocol. Switching protocol clears the other protocol's settings.
- The Issuer URL and the IdP Single Sign-On URL must be https addresses with a public hostname. IP addresses and internal names are refused.
- An OIDC ID token must be signed with RS256 and carry the person's email, in email or in preferred_username. An email taken from preferred_username counts as unverified.
- A SAML assertion must be signed. The email is read from the NameID, or from an email attribute.
- Each sign-in replaces the member's groups with the groups sent in that sign-in. Send the groups on every sign-in. If none are sent, the member's list is emptied and their delegations lapse.
- An account that signs in through the identity provider cannot add or use a passkey. A password account that was later linked to SSO keeps its password and its passkeys.
Customers are different
This page is about the people who work for you. Your customers never sign in to Eniyan and are never members of your account. If your agents act for your customers, you connect your customer identity system (CIAM) instead, as part of consumer delegation. See Connect your customer identity system (CIAM). The two connections are separate, and neither one configures the other.
API and refusal codes
The connection, with an admin's dashboard session and never an API key: GET|PUT|DELETE /v1/idp/connection, POST /v1/idp/connection/test, GET /v1/idp/connection/impact, POST /v1/idp/scim-token. Delegations, with any member's dashboard session: GET /v1/me/entitlements, GET|POST /v1/agents/{agent_id}/delegations, DELETE /v1/agents/{agent_id}/delegations/{id}. Provisioning, with the SCIM token as a bearer token: /scim/v2/Users, /scim/v2/Groups, /scim/v2/ServiceProviderConfig, /scim/v2/ResourceTypes. A missing or wrong SCIM token, or a disconnected connection, answers 401. The SAML service provider metadata is at GET /v1/auth/saml/metadata.
| Code | When |
|---|---|
| INVALID_ISSUER | The issuer or single sign-on URL is not an https address with a public hostname. |
| CLIENT_SECRET_REQUIRED | A new OIDC connection, or a switch to OIDC, was saved without a client secret. |
| OIDC_FIELDS_REQUIRED / SAML_FIELDS_REQUIRED | A field the chosen protocol needs is missing. |
| INVALID_SAML_CERT | The certificate could not be read. Paste the provider's signing certificate, PEM or base64. |
| NO_IDP_CONNECTION | A test or a SCIM token was asked for before a connection was saved. |
| ENTITLEMENT_NOT_HELD | A member tried to delegate a group they do not hold now. |
| NOT_DELEGATION_OWNER | Someone other than the delegator or an admin tried to remove a delegation. |
| DELEGATION_NOT_FOUND | The agent has no such delegation, or it was already removed. |
| PASSKEY_SSO_ACCOUNT | An account that signs in through the identity provider tried to add a passkey. |
A failed sign-in returns the member to the sign-in page with a message. The address carries one of these codes as sso_error:
| Code | When |
|---|---|
| unknown_org | No organization has that slug. |
| sso_not_configured | The organization has no active connection. |
| email_domain_not_allowed | The person's email is outside the allowed email domain. |
| account_link_unverified | The provider did not confirm the email, so the existing account was not linked. |
| access_denied | The person cancelled at the identity provider. |
| invalid_state / state_expired | The sign-in took too long, was used twice, or did not start at Eniyan. Start again. |
| missing_params / no_id_token | The provider's answer was incomplete. Start again. |
| sso_unavailable / sso_failed | Any other failure. The member can try again, or sign in with a password if they have one. |
See also Team, roles & access.