Skip to content

Identity providers

Federate your directory with Okta, Microsoft Entra ID, Google Workspace or another OIDC or SAML identity provider.

Updated View as Markdown

An identity provider is an upstream OIDC or SAML 2.0 provider, such as Okta, Microsoft Entra ID or Google Workspace, that your people already sign in with. You route verified email domains to it: when someone enters an email address in one of those domains at your portal, they’re sent there to sign in, and come back signed in to EZGH SSO. Your applications still trust only EZGH SSO.

A directory can have up to 10 identity providers. You need sso.identityProviders.create.

How federated sign-in works

  1. The person enters their email address at https://<alias>.sso.ezgh.app. Its domain is verified and routed to an identity provider, so they’re sent there. Every address in the domain gets the same answer.
  2. They sign in at the identity provider, which sends them back (OIDC: authorization code with PKCE; SAML: SP-initiated, HTTP-POST to the ACS).
  3. EZGH SSO checks the response and finds the user by the identity provider’s subject (OIDC sub, SAML NameID):
    • Already linked: that user signs in. The email address is never used to find them again, so a changed email at the identity provider doesn’t move the link.
    • First sign-in: the asserted email’s domain must be verified and routed to this identity provider. A user with that email in the directory is linked (a pendingActivation user becomes active; a suspended user is refused). Otherwise a new user is created with source: jit (just in time), counted against your user quota.
    • With SCIM: while a SCIM token names the identity provider, only users its SCIM provisioned can sign in through it, and nobody is created on first sign-in.
  4. Group mappings are applied, and the session starts.

Users created this way have no password, TOTP or passkeys, and sign in only through their identity provider. Suspending or deleting them in EZGH SSO works as for hosted users. Refused sign-ins show an error page on the portal and are recorded in Trails.

Add an identity provider

Add and verify the domains first, then create the identity provider, then route the domains to it with domains. Each domain routes to one identity provider at most (409 domain_in_use), and routes only while it’s verified.

In the console, use EZGH SSO > Identity providers. With the CLI:

ezgh sso identity-providers create --name Okta --protocol oidc --issuer https://acme.okta.com \
  --client-id 0oa1b2c3 --client-secret-stdin --domains acme.com < okta-secret.txt
ezgh sso identity-providers get Okta

With the API, for each protocol:

Register an application at your provider, a web application with a client secret, and give it this redirect URI:

https://<alias>.sso.ezgh.app/federation/oidc/callback

Then create the identity provider:

curl -X POST https://sso.ezghcloud.com/v1/organizations/$ORG_ID/sso/identity-providers \
  -H "Authorization: Bearer $EZGH_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "name": "Okta",
    "protocol": "oidc",
    "oidc": { "issuer": "https://acme.okta.com", "clientId": "0oa…", "clientSecret": "…" },
    "domains": ["acme.com"]
  }'
oidc field Description Default
issuer The provider’s https issuer. Its /.well-known/openid-configuration must name exactly this issuer. Required
clientId The client ID you registered. Required
clientSecret Write-only: it’s never shown again or recorded. clientSecretSet says whether one is set; null removes it.
tokenEndpointAuthMethod client_secret_basic, client_secret_post, or none for a public client. client_secret_basic with a secret, else none
scopes 1 to 20 scopes, including openid. openid email profile
emailClaim The ID token claim with the email address. An email marked email_verified: false isn’t used. email
groupsClaim The ID token claim with the person’s groups. groups

The answer adds redirectUri and, once fetched, the validated discovery. ID tokens must be signed with RS256–512, PS256–512 or ES256–512.

SAML needs the identity provider’s metadata to create it, and the service provider values your identity provider needs contain its ID. So:

  1. Create a SAML application at your identity provider. If it insists on an ACS URL and entity ID before it gives you metadata, enter temporary values.

  2. Create the identity provider with metadataUrl (the provider’s metadata URL) or metadataXml (the metadata document, up to 256 KiB):

    curl -X POST https://sso.ezghcloud.com/v1/organizations/$ORG_ID/sso/identity-providers \
      -H "Authorization: Bearer $EZGH_API_KEY" -H "Content-Type: application/json" \
      -d '{ "name": "Entra ID", "protocol": "saml",
            "saml": { "metadataUrl": "https://login.microsoftonline.com/…/federationmetadata.xml?appid=…" } }'
  3. Enter the answer’s saml.serviceProvider at your identity provider: entityId as the entity ID (audience), and acsUrl as the ACS (reply) URL. metadataUrl serves the same as SAML metadata.

    Value Form
    Entity ID, metadata https://<alias>.sso.ezgh.app/federation/saml/metadata/<identity provider ID>
    ACS URL https://<alias>.sso.ezgh.app/federation/saml/acs/<identity provider ID>
  4. Route the domains: UpdateIdentityProvider with domains.

saml field Description Default
metadataUrl An https URL of the identity provider’s metadata, fetched and refreshed. One of the two is required
metadataXml The metadata itself. It’s checked at once and never refreshed: update it when the provider’s certificate changes.
emailAttribute The attribute with the email address. Empty: the NameID when its format is email address, else a common email attribute (email, mail, emailaddress, the …/claims/emailaddress claim). Empty
groupsAttribute The attribute with the person’s groups. groups

The metadata must describe one identity provider with an https HTTP-Redirect single sign-on URL and 1 to 10 RSA (2048 bits or more) or ECDSA signing certificates. The answer shows its entityId, ssoUrl and certificates with their expiry.

Requirements for responses:

  • Both the response and its assertion must be signed, with SHA-256 or stronger (SHA-1 is refused). Encrypted assertions are refused.
  • Only SP-initiated sign-in: a response that EZGH SSO didn’t ask for (IdP-initiated) is refused.
  • The assertion must name the service provider’s entity ID as its audience, and a NameID that isn’t transient.

Metadata and keys

EZGH SSO fetches OIDC discovery and keys, or SAML metadata, when you create the identity provider or change its issuer or metadata URL, then every 6 hours (every 15 minutes after a failure). RefreshIdentityProviderMetadata fetches within seconds (409 metadata_by_value for SAML given as metadataXml). A failed fetch keeps the last good copy and shows the reason in metadata.error. Until the first fetch succeeds, sign-in through the identity provider is unavailable (503 identity_provider_unavailable). URLs must be public https URLs.

Group mappings

groupMappings adds people to directory groups from the groups the identity provider sends (the OIDC groupsClaim or SAML groupsAttribute): up to 100 { "idpGroup", "groupId" } pairs. idpGroup is the value the provider sends (a name, or an ID for providers that send IDs), or * for everyone who signs in through it. groupId is a directory group you created: groups pushed by SCIM belong to SCIM.

Mappings are applied on every federated sign-in: the person is added to the mapped groups, and removed from groups this identity provider added that no longer match. Memberships you added by hand are left alone.

MFA

With trustUpstreamMfa off (the default) in the sign-in policy, mfaRequired applies only to hosted sign-in, and federated sessions count as single-factor.

With it on, EZGH SSO reads the identity provider’s evidence of multi-factor sign-in: an OIDC amr with mfa or two different methods, or a SAML authentication context for MFA (or Entra ID’s authnmethodsreferences). A sign-in with that evidence is multi-factor (acr urn:ezgh:sso:acr:mfa), and when the directory requires MFA, a sign-in without it is refused.

Provider guides

OIDC (recommended):

  1. In the Okta Admin Console, create an app integration: OIDC - OpenID Connect, Web Application.
  2. Sign-in redirect URIs: https://<alias>.sso.ezgh.app/federation/oidc/callback. Assign the people or groups who should use it.
  3. Copy the Client ID and Client secret. The issuer is your Okta domain, such as https://acme.okta.com (or a custom authorization server’s issuer).
  4. For groups, add a groups claim named groups to the ID token (in the app’s Sign On settings, a groups claim filter). If your setup puts it behind the groups scope, add groups to scopes.

SAML: create a SAML 2.0 app integration. Single sign-on URL is the ACS URL and Audience URI the entity ID; Name ID format EmailAddress, Application username Email. Keep the response and the assertion signed. Add a group attribute statement named groups. Use the app’s metadata URL as metadataUrl.

OIDC:

  1. In the Entra admin center, App registrations > New registration, with a Web redirect URI https://<alias>.sso.ezgh.app/federation/oidc/callback.
  2. Certificates & secrets: create a client secret. The client ID is the Application (client) ID.
  3. The issuer is https://login.microsoftonline.com/<tenant ID>/v2.0.
  4. Token configuration: add the optional email claim to the ID token, and a groups claim. Entra sends group object IDs, so use those as idpGroup in group mappings.

SAML:

  1. Enterprise applications > New application > Create your own application (non-gallery), then Single sign-on > SAML.
  2. Identifier (Entity ID) is the entity ID and Reply URL the ACS URL.
  3. Under SAML Certificates, set Signing option to Sign SAML response and assertion. Entra signs only the assertion by default, which EZGH SSO refuses.
  4. For groups, add a group claim, and set groupsAttribute to its name (http://schemas.microsoft.com/ws/2008/06/identity/claims/groups unless you rename it).
  5. Use the App Federation Metadata Url as metadataUrl.

SAML (sends groups):

  1. In the Google Admin console, Apps > Web and mobile apps > Add custom SAML app.
  2. Download the IdP metadata, and use it as metadataXml (Google doesn’t publish a metadata URL, so update it when Google’s certificate changes).
  3. ACS URL is the ACS URL and Entity ID the entity ID. Select Signed response. Name ID format EMAIL, Name ID the primary email.
  4. Under Group membership, map the groups to an app attribute named groups.
  5. Turn the app on for the people who should use it.

OIDC (no groups): create an OAuth client in the Google Cloud console, type Web application, with the redirect URI above. The issuer is https://accounts.google.com. Make the OAuth consent screen Internal so only your Workspace’s accounts can sign in. Google’s ID tokens carry no groups, so group mappings other than * don’t apply.

Provisioning

provisioning shows how people get into the directory through this identity provider:

  • { "jit": true, "scim": false }: people are created on their first sign-in.
  • { "jit": false, "scim": true }: a live directory SCIM token names this identity provider. Its SCIM provisions people, and only provisioned people sign in through it. See Inbound SCIM.

Delete an identity provider

DeleteIdentityProvider unroutes its domains (people in them sign in hosted from then on), revokes the SCIM tokens that name it, removes the users’ links to it and the group memberships its mappings added, and ends federated sign-ins in progress. The users stay in the directory, and users and groups its SCIM provisioned are unlocked.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close