SSO with OIDC
Connect Okta, Entra ID, Auth0, Keycloak, or any standards-compliant OIDC provider for sign-in.
Eddytor's SSO layer accepts any standards-compliant OIDC provider. There's no admin UI for it yet, so you configure it via the REST API. SSO is a Preview feature, off by default until enabled per-organisation.
This is the end-to-end walkthrough from a clean install.
1. Register an OIDC app at your IdP
The sign-in redirect URI is always ${server.public_url}/v1/oauth/sso/callback.
- Okta: Applications → Create App Integration → OIDC / Web Application. Capture
the Client ID, Client secret, and the issuer URL (e.g.
https://your-tenant.okta.com). - Keycloak / Auth0 / Authentik / others: same pattern, same redirect URI.
2. Get an admin bearer token
The curl calls need one. Mint a non-expiring API key inside the container:
docker compose exec eddytor-server eddytoradm create-api-key --email you@example.com
export EDDYTOR_TOKEN="edd_live_…"3. Look up your organisation ID
ORG_ID=$(curl -fsS http://localhost:8080/api/v1/organisations \
-H "Authorization: Bearer $EDDYTOR_TOKEN" | jq -r '.[0].id')4. Enable the SSO feature flag for the org
curl -fsS -X PATCH "http://localhost:8080/api/v1/organisations/$ORG_ID/config" \
-H "Authorization: Bearer $EDDYTOR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"features":{"sso":true}}'5. Create the OIDC connection
curl -fsS -X POST "http://localhost:8080/api/v1/organisations/$ORG_ID/sso" \
-H "Authorization: Bearer $EDDYTOR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"displayName": "Okta",
"issuerUrl": "https://your-tenant.okta.com",
"clientId": "0oa…",
"clientSecret": "…",
"emailDomain": "example.com",
"enforceSso": false,
"defaultRole": "editor"
}'| Field | Notes |
|---|---|
issuerUrl | Must be https://. Eddytor probes ${issuer}/.well-known/openid-configuration at create time and rejects on failure. |
emailDomain | Lowercase. Sign-ins with an email at this domain route to your IdP instead of magic link. |
enforceSso | true blocks magic-link fallback for the domain. Start false, flip to true once confirmed working. |
defaultRole | One of viewer, editor, builder, admin - granted to first-time sign-ins via this connection. |
6. Smoke-test
Sign out, then hit
${server.public_url}/v1/oauth/authorize?login_hint=alice@example.com in a
browser - Eddytor should 302 you to your IdP, then back through
/v1/oauth/sso/callback into a session.
Update / delete later with PUT / DELETE on
/v1/organisations/$ORG_ID/sso/$CONN_ID.
Callback host override (rare)
If your callback host differs from public_url (e.g. the IdP allow-list is locked
to a single FQDN behind a CDN):
[server]
oauth_redirect_base = "https://idp-callbacks.example.com"The IdP redirect URI must then match ${oauth_redirect_base}/v1/oauth/sso/callback.
Heads up
enforce_sso: true blocks magic-link for that domain.
Confirm the IdP round-trip works with false first, or you can lock yourself
out. The in-container eddytoradm path is still your recovery hatch.Next
- Provider OAuth apps (different feature - cloud-account linking) · redirect_uri mismatch.