Enterprise single sign-on
Any organization owner can connect an OpenID Connect identity provider (Okta, Entra ID, Keycloak, Google Workspace, and the rest) from the organization’s SSO tab, with no operator involved. People who sign in through the connection become members of your organization, joining as readers.
Setup has two independent tiers, so nothing blocks on DNS:
- The connection. It works the moment it is created, through its direct sign-in link. Create it, test it, share the link inside your company; no domain proof is involved.
- Email routing. Typing an email on the shared sign-in page routes to your provider only for domains you claim on the connection and verify with a domain-ownership proof. The proof is re-checked at every sign-in, so a lapsed proof stops routing until it recovers.
Set up your identity provider
Section titled “Set up your identity provider”Register a confidential OIDC client (a “web application”) with your provider:
- Redirect URI:
https://your-haven-instance/auth/callback(the SSO tab shows the exact value to copy). - Grant: authorization code. Haven uses PKCE and validates the
id_tokenagainst the provider’s published signing keys. - Scopes: the connection requests
openid email profileunless you configure others.
Note the client ID and client secret; Haven needs both. The client secret is stored encrypted and is write-only: no Haven response ever contains it.
Connect it to Haven
Section titled “Connect it to Haven”On the SSO tab, enter a name, the issuer URL, and the client
credentials. The issuer is the base URL that serves
/.well-known/openid-configuration; for a Keycloak realm that is
https://idp.example.com/realms/your-realm.
Two optional fields:
- Link name: the short name inside the connection’s sign-in link, defaulting to your organization’s name. It cannot be changed later; it identifies the connection on sign-in links and on the sessions it minted.
- Internal issuer URL: only for split-horizon deployments where
Haven must reach the provider on a different address than the
public issuer. The provider’s configuration must still name the
public issuer. The field only exists on self-hosted deployments
whose operator has set
allow_private_upstreams; everywhere else Haven reaches the provider at its issuer URL, and the API refuses the field.
Test the connection
Section titled “Test the connection”Check configuration fetches the provider’s OIDC configuration through the same path sign-ins use and reports what it found: the authorization, token, and signing-key endpoints, and whether the document names the issuer you configured. It cannot test the client secret.
The full round-trip test is the direct sign-in link on the
connection’s card: open it in a private window and sign in. It
exercises the redirect, the token exchange (and so the secret), and
the id_token validation end to end. This link is also the everyday
sign-in path before email routing is on: bookmark it, put it on your
intranet, or share it in your onboarding docs.
Turn on email routing
Section titled “Turn on email routing”Claim your email domains on the connection, then verify each one in the Domains tab. Once a claimed domain is verified, anyone typing a matching email on the shared sign-in page is routed to your provider. The SSO tab shows each domain’s routing status, and routing follows the proof: if it lapses, routing stops; when it recovers, routing resumes.
A claim without a proof is inert but not useless: it reserves your intent, and it cannot be squatted against you. If another organization claimed your domain without a proof, your verified proof takes the claim over. An organization’s connections can claim at most 20 domains in total, the same ceiling as domain-ownership proofs.
Verification also unlocks invite auto-accept: pending invites to your organization are accepted automatically when the invited person signs in through your connection asserting an email under the proven domain, landing them at the invited role instead of the default reader. This never extends to other organizations’ invites.
Managing the connection
Section titled “Managing the connection”Everything except the link name can be edited in place: label, issuer, client ID, scopes, and the internal issuer. Rotating the client secret is an edit too; leave the field blank to keep the current one. Every change is recorded in the audit log.
Deleting a connection stops its sign-ins immediately, direct link included, and releases its domain claims. Sessions it already minted stay signed in until they expire or sign out.
Troubleshooting
Section titled “Troubleshooting”- “issuer rejected” when saving: Haven fetches the issuer
server-side and refuses private, loopback, and link-local addresses.
On self-hosted deployments whose IdP lives on a private network, the
operator can set
allow_private_upstreamsin the instance configuration. - Check configuration reports an issuer mismatch: the provider’s configuration document names a different issuer than the one you entered. Sign-in fails until they match; usually the issuer URL has a typo or points at the wrong realm or tenant.
- The provider rejects the redirect: the redirect URI registered with your provider must exactly match the one the SSO tab shows.
- Emails stopped routing to the provider: the domain proof has lapsed. Open the Domains tab, restore the record, and press Check now; routing resumes with the proof. The direct link keeps working throughout.