Security

Single sign-on

Your team signs in through your own identity provider, so joiners and leavers are handled where you already handle them. Any provider that speaks OpenID Connect works, an admin sets it up in a few minutes, and there is a test button that proves the round trip before anyone else is affected.

What you need from your provider

Create an application in your identity provider (Okta, Entra ID, Keycloak, Google Workspace, anything OIDC) and collect four things:

SettingWhat it is
Issuer URLThe base your provider publishes its discovery document under, for example https://login.example.com. We read /.well-known/openid-configuration there to find your sign-in endpoints, so a typo is caught on the screen where you typed it rather than at your first employee's first sign-in.
Client IDFrom the application you just created.
Client secretStored encrypted and never returned by the API. Leave the field empty on a later edit to keep the one you already saved.
Email domainsThe domains that route to you, for example acme.com, acme.co.uk. Anyone signing in with an address at these is sent to your provider. A domain belongs to exactly one workspace across Engram, so a domain already claimed elsewhere is refused with a 409.

In your provider's application you need one redirect URL from us, which is the same string for every customer: https://api.engramdynamics.org/auth/sso/callback. The security page shows the exact value for the deployment you are on, and so does GET /enterprise/sso in the redirect_uri field, on any plan and before anything is configured. We ask for the scopes openid email profile and nothing else, so no directory read permission is involved.

Configure it

In the app: Settings, Security, Single sign-on. Over the API, one call writes the whole configuration:

curl -s -X PUT https://api.engramdynamics.org/enterprise/sso \
  -H "Authorization: Bearer <your key>" \
  -H "Content-Type: application/json" \
  -d '{
        "issuer": "https://login.example.com",
        "client_id": "engram-web",
        "client_secret": "<client secret>",
        "email_domains": ["acme.com", "acme.co.uk"],
        "enforced": false
      }'
{
  "enabled": true,
  "issuer": "https://login.example.com",
  "client_id": "engram-web",
  "client_secret_set": true,
  "email_domains": ["acme.com", "acme.co.uk"],
  "enforced": false,
  "redirect_uri": "https://api.engramdynamics.org/auth/sso/callback",
  "start_url": "https://app.engramdynamics.org/login?sso=1"
}

The write is validated against the real provider before anything is stored: we fetch your discovery document and check it names the same issuer and carries the endpoints the flow needs. A bad issuer fails here, with a plain-words message, instead of silently later.

Test it before you require it

The test button hands you an authorization URL built exactly the way a real sign-in builds one. Open it in a new tab: a wrong client id or an unregistered redirect URL shows up as your provider's own error, on your provider's own page, which is the clearest place for it to appear.

curl -s -X POST https://api.engramdynamics.org/enterprise/sso/test \
  -H "Authorization: Bearer <your key>"
{
  "authorization_url": "https://login.example.com/authorize?response_type=code&...",
  "redirect_uri": "https://api.engramdynamics.org/auth/sso/callback",
  "expires_in": 600
}

How a sign-in works

A person types their work address on the sign-in page. We map the domain to your workspace and send them to you:

curl -s -X POST https://api.engramdynamics.org/auth/sso/start \
  -H "Content-Type: application/json" \
  -d '{"email": "dana@acme.com"}'

They authenticate with you, your provider calls the one redirect URL back, and we mint the session. Points worth knowing:

Requiring it

Turn on Require it, or send "enforced": true, and passwords stop working for the whole workspace: a password sign-in is refused and the person is sent to your provider instead. Test the round trip first.

Enforcement is the setting that can lock a workspace out, so it is also the setting we never let a plan trap you on. Turning single sign-on off is not plan-gated on any tier: a workspace that moves down to a plan without SSO can always switch it off and get its passwords back.

curl -s -X DELETE https://api.engramdynamics.org/enterprise/sso \
  -H "Authorization: Bearer <your key>"

That forgets the whole configuration, the stored secret included.

When it does not work

What you seeWhat it means
409 on save, naming a domainAnother workspace already claims that domain. Get in touch if that is not right.
400 on save, about the discovery documentThe issuer URL is wrong or unreachable. Many providers publish per-realm, so the issuer is https://host/realms/acme, not the host root.
sso_not_configuredThe address does not map to a workspace with SSO turned on.
sso_expiredThe sign-in attempt took longer than ten minutes. Start again from the sign-in page.
sso_wrong_workspaceYour provider asserted an address that already belongs to another workspace.
seat_limitThe workspace is at its seat cap, so the new person was not provisioned. See the plan table.
403 plan_feature on writeReading the settings is open on every plan; writing them needs the plan that carries single sign-on.

Next

IP allowlist restricts where requests can come from, and pairs naturally with single sign-on. API keys and scopes covers the machine credentials, which SSO does not replace.