Wiki
Concepts

Single Sign-On & SCIM

Sign in through an identity provider, and let it manage the member list.

Instead of a password per person, an organization can point Wiki at its own identity provider — Entra ID, Okta, Keycloak, Authentik, Google Workspace, or anything else that speaks OpenID Connect.

Two independent features, usually adopted in this order:

FeatureWhat it doesOptional?
SSO (OIDC)People sign in with their work account; a member is created on first use
SCIM (directory sync)The provider creates, updates and deactivates members by itselfyes

Both are configured in the app, under Settings → Single Sign-On — not through environment variables — so adding a provider never needs a redeploy.

Who may configure this

Only the owner and admins of an organization. Unlike the rest of the settings area, a custom group cannot grant it: Better Auth's SSO and SCIM plugins ship their own authorization that only understands the static roles.

Connecting an identity provider

1. Create an application in the provider

Create an OIDC web application. It will ask for a redirect URI (also called callback URL):

https://<your-server>/api/auth/sso/callback/<provider-id>

<provider-id> is a short name you choose — okta, entra, keycloak. The exact URL is shown, ready to copy, in the "Anbieter verbinden" dialog as soon as you type the ID.

Note the client ID and client secret the provider issues.

2. Fill in the dialog

FieldExampleNotes
Anbieter-IDoktaImmutable — it is part of the redirect URI and of every login
E-Mail-Domainacme.comComma-separated for several domains behind one provider
Issuer-URLhttps://acme.okta.comWithout /.well-known/openid-configuration
Client-ID0oa1b2c3…From the provider
Client-SecretStored server-side, never shown again

Saving performs OIDC discovery against the issuer, so a wrong URL is rejected immediately rather than at the first sign-in attempt.

3. Verify the domain

A newly connected provider is not yet live. Sign-in stays refused until the e-mail domain is verified with a DNS TXT record:

RecordValue
Name_better-auth-token-<provider-id>.<domain>
TypeTXT
Valueshown in the "Domain bestätigen" dialog

The exact name is shown ready to copy, once per domain. Then press Jetzt prüfen. The token is valid for seven days, and re-opening the dialog shows the same value rather than invalidating the record you already published.

Why this step is not optional

Sign-in resolves the provider purely from the typed address' domain. Without proof of ownership, an administrator of any organization on the instance could claim gmail.com and intercept those sign-ins. Verification is also what allows an SSO login to adopt a pre-existing local account with the same address instead of creating a second one for the same person.

The server must be able to resolve DNS

The check runs from the server process (dns.resolveTxt). An air-gapped install that cannot resolve the e-mail domain's public TXT records cannot complete this step — and therefore cannot use SSO.

Signing in

The login screen has a Mit Firmenkonto anmelden button. It reuses the address already typed in the e-mail field, matches it against the configured domains, and redirects to the provider. The two ways this can fail are told apart rather than lumped into one message: no provider for that domain, and a provider whose domain is not verified yet — the second being the one people hit while a rollout is half-finished.

Whoever signs in this way is added to the provider's organization as a member. Elevating them stays a deliberate act in Settings → Mitglieder.

Directory sync (SCIM)

Without SCIM, an account appears the first time someone signs in, and removing someone from the provider does not remove them here. SCIM closes both gaps.

  1. Settings → Single Sign-On → Verbindung erstellen, pick an ID (okta-scim).
  2. Copy the base URL and the bearer token — the token is shown exactly once; only its hash is stored.
  3. Paste both into the provider's Provisioning configuration.
Base URL:   https://<your-server>/api/auth/scim/v2
Auth:       Authorization: Bearer <token>

Supported resources: Users (list, get, create, replace, patch, delete) plus the standard ServiceProviderConfig, Schemas and ResourceTypes discovery endpoints.

Every token is bound to one organization — provisioned users land there. Tokens that belong to no organization are refused outright, because such a token could provision users instance-wide.

Rotating a token replaces the old one immediately; sync stands still until the new one is stored in the provider. Removing a connection invalidates the token but leaves already-synced members untouched.

What is not exposed

  • SAML. The server supports it, but the settings UI is OIDC-only: SAML needs certificates and assertion mappings that do not belong in a dialog. OIDC covers every provider listed above.
  • IdP-initiated sign-in. Starting from the provider's dashboard tile is not wired up; start from the wiki's login screen.
  • SCIM Groups. Only Users is implemented. Teams and groups stay managed in the app.

Operational notes

  • Rate limiting. SCIM traffic is machine traffic — one request per directory user, all from one IP. It gets its own ceiling, RATE_LIMIT_SCIM_MAX (default 1200/minute), instead of the much tighter RATE_LIMIT_AUTH_MAX.
  • Secrets at rest. A provider's client secret is stored in the database in plain text (auth.sso_provider.oidc_config). Treat database backups accordingly — see Backups.
  • Deleting an organization removes its providers and SCIM connections with it (ON DELETE CASCADE), so a deleted tenant cannot keep authenticating.
  • Removing a provider deletes every linked login. Someone who only ever signed in through it keeps their account and content but needs a new way in — the confirmation dialog says so, and requires typing the provider ID.

On this page