SAML
SAML through the SSO plugin via samlify (never hand-rolled XML).
import { createShelfAuth, samlPreset } from "@storyshelf/auth";
const shelf = createShelfAuth({ db: database, secret: process.env.SECRET!, baseURL: process.env.PUBLIC_BASE_URL!, sso: { providers: [ samlPreset({ id: "acme-saml", domain: "example.com", issuer: process.env.PUBLIC_BASE_URL!, entryPoint: "https://idp.example.com/sso", metadataXml: "{env:SAML_METADATA}", }), ], },});Hand the IdP admin the callback URLs from ssoCallbackUrls(baseURL, providerId) (ACS, SP metadata). Users link by email on first sign-in.
Group sync
Section titled “Group sync”samlPreset({ // ... groupsAttribute: "http://schemas.example.com/groups", // SAML attribute (default "groups") adminGroups: ["Acme Admins"],});Same reconcile rules as OIDC: exact match, site admin ↔ member on every sign-in, sso:<group> project grants, manual grants survive.
For OIDC discovery, see OIDC; for secrets and precedence, see Configuration.