SAML single sign-on
Requires a license with the
samlfeature. See pricing.
SAML single sign-on lets your team sign in to the admin console through your company's identity provider. LyEve acts as the SAML service provider: it sends people to the provider, checks the signed answer that comes back, and starts a console session. Each tenant has its own providers.
How it works
Section titled “How it works”| Step | What happens |
|---|---|
| Start | The browser opens /api/admin/auth/saml/{provider}. LyEve redirects it to the provider with a signed request. |
| Sign in | The person signs in at the provider. |
| Assertion | The provider posts its answer to /api/admin/auth/saml/{provider}/acs. LyEve checks it and finds or creates the account by email. |
| Session | LyEve sets the session cookie and redirects to /admin, or to the path given in ?redirect=. |
What you can rely on:
- Sign-in starts from LyEve. An answer the provider sends without a request from LyEve is refused.
- Each assertion is accepted once. A replayed assertion is refused with
409. - An answer larger than 1 MiB, or one carrying a
DOCTYPEor entity declaration, is refused. - The provider can never grant
adminorsuper_admin. Those roles are dropped. A new user with no other role getseditor. - LyEve signs its requests with a certificate it generates for each provider, valid for one year. The private key is encrypted at rest and never returned.
- A sign-in for an email that already has an account in the tenant signs in to that account, with the roles stored in LyEve. The provider decides who may claim which email, so connect only a provider you trust with every account in the tenant.
Turn it on
Section titled “Turn it on”- Run with a license that carries
saml. See licensing and tiers. - Set
LYEVE_BASE_URLto the public address of the instance. In production, sign-in refuses to start without it. - Set
SECURE_COOKIE=truewhen the instance is served over HTTPS. - Restart the instance and add a provider. A super admin opens Access > SAML SSO in the admin console and chooses New provider, or uses the API below.
- Give your provider the addresses in Register LyEve with the provider.
On an instance with several tenants, the sign-in routes take the tenant from the domain the request arrives on. Map a domain to each tenant that uses SAML. See tenants.
Try it
Section titled “Try it”You need a super admin token in TOKEN. The
quickstart shows how to get one.
-
List the templates:
Terminal window curl http://localhost:3001/api/admin/saml-templates \-H "Authorization: Bearer $TOKEN"[{ "key": "okta", "name": "Okta", "description": "Okta Workforce Identity Cloud SAML 2.0 integration." },{ "key": "azure-ad", "name": "Azure AD / Entra ID", "description": "Microsoft Azure Active Directory / Entra ID SAML 2.0 integration." },{ "key": "onelogin", "name": "OneLogin", "description": "OneLogin SAML 2.0 SSO integration." }] -
Read the settings Okta expects. Nothing is saved:
Terminal window curl -X POST http://localhost:3001/api/admin/saml-templates/apply \-H "Authorization: Bearer $TOKEN" \-H "Content-Type: application/json" \-d '{"key": "okta"}'The answer holds
key,name,descriptionand aconfigwith the signature settings, the attribute mapping and anidp_cert_hintsaying where Okta shows its certificate. -
Create the provider with the values from Okta:
Terminal window curl -X POST http://localhost:3001/api/admin/saml-providers \-H "Authorization: Bearer $TOKEN" \-H "Content-Type: application/json" \-d '{"name": "okta","entity_id": "http://www.okta.com/exk1a2b3c4d5e6f7g8h9","sso_url": "https://example.okta.com/app/example_lyeve/exk1a2b3c4d5e6f7g8h9/sso/saml","idp_cert": "-----BEGIN CERTIFICATE-----\nMIID...\n-----END CERTIFICATE-----","attributes_mapping": {"email": "email", "roles": "groups"},"enabled": true}'The answer is
201with the provider, itssp_cert_active, andsp_cert_expires_atandidp_cert_expires_at. CopyidintoPROVIDER_ID. -
Fetch the metadata to give Okta:
Terminal window curl http://localhost:3001/api/admin/auth/saml/okta/metadataThe answer is the service provider's metadata XML.
-
Open Access > SAML SSO in the admin console. The provider is listed with its certificate expiry dates, and the login page offers it.
Register LyEve with the provider
Section titled “Register LyEve with the provider”For a provider named okta, give your identity provider:
| Setting at the provider | Value |
|---|---|
| Assertion consumer service (ACS) URL | {LYEVE_BASE_URL}/api/admin/auth/saml/okta/acs |
| SP entity ID (audience) | The same ACS URL |
| SP metadata | {LYEVE_BASE_URL}/api/admin/auth/saml/okta/metadata |
Many providers read everything from the metadata URL. The provider must send
the user's email in the attribute named in attributes_mapping.email.
To sign in, send the browser to /api/admin/auth/saml/okta. Add
?redirect=/admin/content to land on another page of the console afterwards.
Only a path on the same site is accepted.
Provider fields
| Field | Meaning | Default |
|---|---|---|
name | Used in the sign-in URL. Unique in the tenant | required |
entity_id | The provider's entity ID | required |
sso_url | The provider's single sign-on URL | required |
slo_url | The provider's single logout URL | none |
idp_cert | The provider's signing certificate, PEM. Never returned | required |
name_id_format | The NameID format to request | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress |
attributes_mapping | Which assertion attributes hold the email and the roles | {"email": "email", "roles": "groups"} |
want_assertions_signed, want_response_signed, sign_authn_requests | Signature requirements. A new provider always starts with all three on | true |
want_authn_signed, encrypt_assertions | Further signature and encryption options | false |
enabled | Whether the login page offers it | false |
Rotate the signing certificate
Section titled “Rotate the signing certificate”Rotate in two steps so sign-in never breaks:
-
Stage a new certificate. The answer shows it as
sp_cert_next, and the metadata then lists both certificates:Terminal window curl -X POST http://localhost:3001/api/admin/saml-providers/$PROVIDER_ID/prepare-cert \-H "Authorization: Bearer $TOKEN" -
Wait until the provider has read the new metadata, or upload the new certificate there by hand. Then promote it:
Terminal window curl -X POST http://localhost:3001/api/admin/saml-providers/$PROVIDER_ID/rollover-cert \-H "Authorization: Bearer $TOKEN"
Both calls return the provider. Promoting before staging answers
400 no next certificate configured. The console shows the same two steps,
and counts the certificates that are expired or close to expiry under
Certificates to renew.
Settings
Section titled “Settings”| Variable | What it does | Default |
|---|---|---|
LYEVE_BASE_URL | Public address the ACS and metadata URLs are built from. Required when APP_ENV is production. | unset |
APP_ENV | Outside production, a missing LYEVE_BASE_URL falls back to the request's host. | production |
SECURE_COOKIE | Marks the sign-in cookies Secure. | false |
JWT_EXPIRY_SECS | Lifetime of the session a sign-in creates. | 900 |
If you set LYEVE_PLUGINS, include saml in it.
Routes
Section titled “Routes”Every route that needs a role takes a signed-in session. An admin token is
refused on them with 403.
Sign-in, providers and templates
| Method | Path | Role | Purpose |
|---|---|---|---|
GET | /api/admin/auth/saml-providers | public | Names of enabled providers, for login buttons |
GET | /api/admin/auth/saml/{provider} | public | Start sign-in. Redirects to the provider |
POST | /api/admin/auth/saml/{provider}/acs | public | Where the provider posts its answer |
GET | /api/admin/auth/saml/{provider}/metadata | public | LyEve's metadata XML for that provider |
GET | /api/admin/saml-providers | admin | List providers, including disabled ones |
POST | /api/admin/saml-providers | super_admin | Add a provider. 201 |
PUT | /api/admin/saml-providers/{id} | super_admin | Change a provider |
DELETE | /api/admin/saml-providers/{id} | super_admin | Remove a provider. 204 |
POST | /api/admin/saml-providers/{id}/prepare-cert | super_admin | Stage a new signing certificate |
POST | /api/admin/saml-providers/{id}/rollover-cert | super_admin | Promote the staged certificate |
GET | /api/admin/saml-templates | admin | List the templates |
GET | /api/admin/saml-templates/{key} | admin | Read one template |
POST | /api/admin/saml-templates/apply | super_admin | Return a template's settings without saving anything |
Errors
Section titled “Errors”| Status | Message | Cause |
|---|---|---|
404 | provider not found | No enabled provider of that name in the tenant. |
401 | SAML authentication failed | The answer did not verify, or LyEve did not ask for it. |
409 | assertion already consumed | The same assertion was sent twice. |
401 | identity provider did not provide an email address | The email attribute is missing. |
Every other error
| Status | Message | Cause |
|---|---|---|
401 | authentication failed | The account is disabled or expired. |
400 | no next certificate configured | rollover-cert was called before prepare-cert. |
400 | key is required | apply was called without a template key. |
404 | template not found | No template has that key. |
415 | unsupported media type, expected application/json or multipart/form-data | A body in any other format. |
404 | The requested endpoint does not exist. | The instance started without a license that carries saml. |
402 | payment_required | The license stopped carrying saml while the instance was running. |
Troubleshooting
Section titled “Troubleshooting”- Sign-in fails right after the provider's login page. Check that the ACS
URL and entity ID at the provider match the table above, and that
LYEVE_BASE_URLis the address users reach. - Users land without the roles they expect. Check
attributes_mapping.rolesagainst the attribute your provider sends. An existing account keeps its LyEve roles.adminandsuper_adminare never taken from the provider, so grant them in LyEve.
Related
Section titled “Related”- Sign-in options: every way to sign in, side by side.
- SCIM provisioning: create and remove accounts from the same directory.
- OAuth sign-in: for OpenID Connect providers.
- Tenants: map a domain to each tenant.