SSO is off by default. Existing deployments that don’t configure it see no change — the sign-in page stays exactly as before, with only the magic-code form.
How it works
Notifuse acts as an OIDC Relying Party using the Authorization Code flow with PKCE:- The user clicks Sign in with SSO → Notifuse redirects them to your IdP.
- The user authenticates at the IdP (with whatever MFA/policies you enforce there).
- The IdP redirects back to
…/api/user.oidc.callback; Notifuse verifies the ID token server-side (signature, issuer, audience, nonce, expiry) and signs the user in.
Login is not the same as workspace access. A successful SSO login authenticates the user; it does not grant access to any workspace. SSO users still need a workspace invitation (or to be a
ROOT_EMAIL) before they can do anything. See Provisioning below.Configuration
OIDC can be configured three ways, in this precedence order:- Environment variables (
OIDC_*) — recommended for production; these always win. - Setup Wizard — an optional SSO step on first launch.
- Settings → SSO — an admin drawer in the console after install.
Environment variables
Provisioning
By default, SSO is invited-users-only: a user can sign in with SSO only if they already have a Notifuse account or have been invited to a workspace (see Invited users). An SSO login for an address nobody invited is rejected with a “no account” message. This preserves Notifuse’s no-self-signup model. To let new users be created automatically on first SSO login, set:OIDC_ALLOWED_DOMAINS. Even then, the new user has no workspace access until invited. An address with an invitation waiting follows the Invited users rules instead, both ways: the invitation can create the account outside the allowlist, and a provider that is not authoritative for the address creates none.
Invited users
An invitee doesn’t need to open the emailed link before signing in with SSO. On their first SSO login, a pending invitation to their address creates their account — in invited-only mode, and even when their domain is not inOIDC_ALLOWED_DOMAINS, since an invitation is an owner’s explicit choice of that one address. The invitation is not accepted for them: they land on the workspace list, under Pending invitations, and click Join.
That only happens when your identity provider is authoritative for the address, because joining from the console relies on the address the provider asserts:
When the provider is not authoritative, SSO creates no account for an invited address — not even with
OIDC_AUTO_CREATE_USERS — and the invitee opens the link in their invitation email instead. Once they have accepted it, SSO works for them from then on.
Users are matched by the durable
(issuer, subject) pair from the IdP, not by email — so a user keeps the same account even if their email changes at the IdP. Email is used only on first login: to link an SSO identity to an existing account, or to find the invitations waiting for that address. A ROOT_EMAIL account can never be auto-linked to an external identity (a safeguard against platform-admin takeover).Identity provider setup
The callback/redirect URL to register at every provider is:Google Workspace
- In the Google Cloud Console, go to APIs & Services → Credentials → Create credentials → OAuth client ID.
- Choose Web application.
- Under Authorized redirect URIs, add
https://<your-notifuse-domain>/api/user.oidc.callback. - Copy the Client ID and Client secret.
- Configure Notifuse:
Personal
@gmail.com accounts and your Workspace accounts share the accounts.google.com issuer. Use OIDC_ALLOWED_DOMAINS (or keep the default invited-only mode) to restrict sign-in to your organization. A @gmail.com address you have invited can still sign in — see Invited users.Keycloak
- In your realm, create a client: Client type OpenID Connect, Client authentication ON (confidential), Standard flow enabled.
- Set Valid redirect URIs to
https://<your-notifuse-domain>/api/user.oidc.callback. - Copy the secret from the client’s Credentials tab.
- Configure Notifuse:
Other providers
Any OpenID-Connect–certified provider works the same way — setOIDC_ISSUER_URL to the provider’s issuer, register the redirect URI, and supply the client ID/secret. This includes Okta, Microsoft Entra ID (Azure AD), Authentik, and Dex.
Security notes
- Only two non-secret values reach the browser:
window.OIDC_ENABLEDand the button label. The client ID, client secret, and issuer URL are never exposed in the page. - ID tokens are verified with the issuer’s published keys (auto-rotated via JWKS); signature, issuer, audience, nonce, and expiry are all checked, and only asymmetric algorithms (RS256/ES256) are accepted.
- The flow’s CSRF/nonce/PKCE state is held in a short-lived, encrypted,
HttpOnlycookie. - OIDC HTTP calls (discovery, key fetch, token exchange) are time-bounded, so a slow or unreachable issuer cannot stall the sign-in path; magic-code login is unaffected.
Troubleshooting
Running multiple Notifuse replicas behind a load balancer? The one-time code used to complete the SSO handoff is held per-instance, so enable sticky sessions for SSO to work reliably across replicas. Single-instance deployments need no extra configuration.
