OIDC
Domain-routed OIDC through the SSO plugin via IdP discovery (never hand-rolled).
import { createShelfAuth, ssoKeycloakPreset } from "@storyshelf/auth";
const shelf = createShelfAuth({ db: database, secret: process.env.SECRET!, baseURL: process.env.PUBLIC_BASE_URL!, sso: { providers: [ ssoKeycloakPreset("https://idp.example.com/realms/shelf", { domain: "example.com", clientId: "storyshelf", clientSecret: "{env:OIDC_CLIENT_SECRET}", }), ], },});Recipes: ssoKeycloakPreset, ssoOktaPreset, ssoAuth0Preset, ssoGooglePreset, ssoEntraPreset. Hand the IdP admin the callback URLs from ssoCallbackUrls(baseURL, providerId) (OIDC callback). SSO users link by email on first sign-in and keep existing shelf roles.
IdP group sync
Section titled “IdP group sync”Recipes accept group options — synced on every sign-in (social and generic-OAuth logins have no per-login hook and never sync):
ssoKeycloakPreset("https://idp.example.com/realms/shelf", { domain: "example.com", clientId: "storyshelf", clientSecret: "{env:OIDC_CLIENT_SECRET}", groupsClaim: ["groups", "cognito:groups"], // OIDC claim names (default ["groups"]) adminGroups: ["shelf-admins"], // exact match → site admin});- Claim values pass through as arrays; a lone string counts as one group (never whitespace-split). Matching is exact — no wildcards.
- Site role reconciles fully: admin-group members become
admin, everyone else resets tomemberon each sign-in. - Project memberships follow the Members-tab group mappings (highest rank wins, recorded as
sso:<group>); stale synced grants are revoked while manual grants survive.
Relying-party discovery
Section titled “Relying-party discovery”StoryShelf is an OIDC relying party, not a provider:
GET /.well-known/openid-configuration— RP metadata (issuer,codeflow, scopes, per-providerredirect_uris, provider list). SetPUBLIC_BASE_URLso the issuer is stable: without a confirmed public origin it names the address of the request it answers.GET /.well-known/change-password— redirects to/profile.
For SAML, see SAML; for generic config and secrets, see Configuration.