External sign-in (Google, Apple, Facebook)¶
Identity is deliberately split into two tables:
user who somebody is — owns a library
auth_identity how they prove it — 'local' password, 'google' sub, …
A password is just an identity with provider='local'. Adding an OAuth provider
inserts rows into auth_identity and changes nothing else, and one person can
hold several identities pointing at the same library.
To enable a provider: register an OAuth client with them, then paste the
client id and secret into Admin → Sign-in providers. The page shows the exact
redirect URI to register. Its button then appears on the sign-in page. Nothing
else needs configuring — the flow is authorization-code with PKCE, state is kept
server-side and consumed once, and ID token aud, iss and exp are checked.
Linking to an existing library. Someone who already signed up with a password can link Google from their account page and keep everything they have. A first-time Google sign-in whose verified email matches an existing account links to it rather than creating a second, empty one — which is why the registration form asks for an email.
Provider notes:
- Google works with the shipped configuration; you only supply credentials.
- Apple uses a short-lived ES256 JWT as its client secret rather than a
fixed string. Mint one and paste it as the secret, or extend
oauth._client_secret()to sign it per request. - Facebook is plain OAuth2 rather than OIDC, so the profile comes from the
Graph
/meendpoint instead of an ID token. The registry entry handles that.
Behind a reverse proxy, set LONGBOX_PUBLIC_URL so callbacks point at your
external hostname rather than the container's.
Security notes¶
Passwords are hashed with scrypt (N=16384, r=8, p=1) and a per-password salt,
verified in constant time. Session tokens are 256 bits of randomness, stored
only as a SHA-256 hash, so a database leak does not hand out live sessions.
Cookies are HttpOnly and SameSite=Lax, plus an Origin check on every
state-changing request. Repeated failed sign-ins are throttled per
username-and-address. Changing a password or disabling an account revokes every
existing session.
Password reset tokens follow the same rules as sessions: 256 bits of randomness, stored only as a SHA-256 hash, single use, and short-lived. Consuming one revokes every session for that account.
Longbox still expects to live on a trusted network. Put it behind a reverse
proxy with TLS if you expose it, and set LONGBOX_SECURE_COOKIES=1 when you do
-- see Reverse proxy and HTTPS.