Single sign-on (OIDC)
Tome can authenticate against an external OpenID Connect identity provider, so you and your users sign in with the same identity (and passkeys, if your IdP supports them) you use everywhere else. It works with any compliant OIDC provider — Pocket ID, Authelia, Authentik, Keycloak, Zitadel, Google, and more. The examples below use Pocket ID, but the Tome side is standard OIDC.
How it works
Tome acts as an OIDC relying party. When a user clicks Sign in with SSO, Tome redirects to your IdP; after they authenticate, the IdP redirects back and Tome mints its normal session token. Because the callback issues the same token as a password login, everything downstream — the API, OPDS, the KOReader plugin, API tokens — is unchanged.
The IdP's groups claim maps to a Tome role (admin / member / guest), so you manage access from your identity provider.
1. Register Tome at your IdP
In your provider, create an OIDC client/application for Tome:
- Create a new OIDC client named e.g.
Tome. - Set the callback / redirect URL to
https://tome.example.com/api/auth/oidc/callback(your public Tome URL + that path). - Keep it a confidential client (it has a secret) and enable PKCE.
- Optional — set a client logo: paste
https://tome.bndct.sh/tome-icon.png, or download it and host it yourself (recommended if you'd rather not depend on this site staying up). - Copy the Client ID and Client Secret.
- Create groups for your roles — e.g.
tome_adminsandtome_members— and add your users. If your IdP gates access per-client (Pocket ID's "Allowed User Groups"), include those groups so thegroupsclaim is emitted.
2. Configure Tome
Set these environment variables on your Tome container and restart:
TOME_OIDC_ENABLED=true
TOME_OIDC_ISSUER=https://auth.example.com
TOME_OIDC_CLIENT_ID=<from your IdP>
TOME_OIDC_CLIENT_SECRET=<from your IdP>
TOME_OIDC_ADMIN_GROUP=tome_admins
TOME_OIDC_MEMBER_GROUP=tome_members
TOME_OIDC_DEFAULT_ROLE=guest
# Behind a reverse proxy, pin your public origin so the redirect is correct:
TOME_PUBLIC_URL=https://tome.example.com | Variable | Purpose |
|---|---|
TOME_OIDC_ENABLED | Master switch (default false). |
TOME_OIDC_ISSUER | Your IdP base URL. Tome appends /.well-known/openid-configuration. |
TOME_OIDC_CLIENT_ID / _SECRET | Credentials from the IdP client. |
TOME_OIDC_REDIRECT_URL | Explicit callback URL. Optional — derived from TOME_PUBLIC_URL / the request origin otherwise. See behind a proxy. |
TOME_OIDC_ADMIN_GROUP | Group whose members become Tome admins. |
TOME_OIDC_MEMBER_GROUP | Group → member. |
TOME_OIDC_GUEST_GROUP | Group → guest. |
TOME_OIDC_DEFAULT_ROLE | Role when no group matches (default guest). |
TOME_OIDC_ROLE_SYNC | login (IdP is truth every login) or create (role set once, then editable in Tome). Default login. |
TOME_OIDC_AUTO_CREATE | Provision unknown IdP users on first login (default true). Set false to allow only pre-existing/linked accounts. |
TOME_OIDC_ALLOWED_GROUP | If set, membership is required to sign in at all. |
TOME_OIDC_GROUPS_CLAIM | Claim carrying group membership (default groups). |
TOME_OIDC_BUTTON_LABEL | Login-page button text (default Sign in with SSO). |
With SSO enabled, a Sign in with SSO button appears on the login page. Done.
Group → role mapping
On each login Tome reads the groups claim and resolves a role, admin first:
| If the user is in… | Tome role |
|---|---|
TOME_OIDC_ADMIN_GROUP | admin |
TOME_OIDC_MEMBER_GROUP | member |
TOME_OIDC_GUEST_GROUP | guest |
| none of the above | TOME_OIDC_DEFAULT_ROLE |
Adding SSO to an existing account
Already have a Tome account with your library, reading progress, and shelves? Link SSO to it instead of creating a second account:
- Sign in to your existing account with your password (not SSO).
- Go to Settings → Single Sign-On → Link SSO and authenticate at your IdP.
- From then on, Sign in with SSO lands you in that same account. Your password keeps working too.
Behind a reverse proxy
If Tome runs behind a TLS-terminating reverse proxy (Caddy, Traefik, Pangolin, nginx, …), the app
server sees plain http internally. Left unhandled, Tome would hand your IdP an
http:// redirect URL that won't match the https:// one you registered, and
the login would fail.
Pick one:
- Set
TOME_PUBLIC_URL=https://tome.example.com(recommended — it also pins the KOReader plugin URL), or - Set
TOME_OIDC_REDIRECT_URL=https://tome.example.com/api/auth/oidc/callbackexplicitly, or - Ensure your proxy forwards
X-Forwarded-Proto: https(Tome honors it).
Logout
Logging out of Tome clears your Tome session only — it does not end your IdP session. If your IdP still has an active session, the next Sign in with SSO may sign you straight back in without a fresh prompt. To fully sign out, also log out at your identity provider.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Button doesn't appear | TOME_OIDC_ENABLED not true, or issuer/client not all set. |
| IdP rejects the redirect | Registered callback doesn't match Tome's (often http vs https behind a proxy — see above). |
Everyone lands as guest | The groups claim isn't arriving — check the client emits it and TOME_OIDC_GROUPS_CLAIM matches. |
| A duplicate account appeared | Signed in via SSO before linking — see account linking. |