Auth: verifiable end-user identity (JWT / OIDC)#84
Merged
Conversation
Optionally verify a caller's token into a trusted req.user, without touching the
zero-config default (identity is off until configured).
- Configure AUTH_JWT_SECRET (HS256) or AUTH_JWKS_URL + AUTH_JWT_ISSUER/AUDIENCE
(OIDC, RS/ES). Verification uses jose (not hand-rolled); an invalid/expired/
wrong-iss-or-aud token, or one missing `sub`, is a clean 401.
- A token is read from Authorization: Bearer <jwt> (only when JWT-shaped, so it
never clashes with an api/project key), the X-User-Token header, or ?token=
(websockets can't set headers). The auth hook sets req.user and:
* echoes it at GET /v1/me (always reachable),
* uses sub as the trusted realtime presence identity (overrides ?as=),
* on an API_KEY-locked instance, accepts a valid token in place of the key
(end-users auth with their own IdP token instead of a shared secret).
Multi-tenant project keys still scope the request; identity layers on top.
- SDK: Zero(base, { token }) sends X-User-Token + ?token=; client.me().
- Row-level per-user authorization is intentionally deferred (next step) to keep
this surface small and stable.
Verification: 74/74 SQLite (+ identity tests: HS256 auth/echo/locked-mode/invalid,
OIDC RS256 via a JWKS endpoint with iss/aud enforcement, and trusted presence
overriding ?as=), 53/53 Postgres 16, Redis suite green. Docs updated
(.env.example, README, /docs, roadmap).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Optional verifiable end-user identity (JWT / OIDC). When configured, a caller's token is verified into a trusted
req.user; the zero-config default is unchanged (identity is off until you set it). The last roadmap item for today.How
AUTH_JWT_SECRET(HS256) orAUTH_JWKS_URL+AUTH_JWT_ISSUER/AUTH_JWT_AUDIENCE(OIDC, RS/ES). Verification usesjose(not hand-rolled crypto); a bad signature / wrongiss/aud/ expired /sub-less token is a clean401.Authorization: Bearer <jwt>(only when JWT-shaped, so it never clashes with an api/project key), theX-User-Tokenheader (coexists with a project key), or?token=(websockets can't set headers). The auth hook then:GET /v1/me(always reachable),subas the trusted realtime presence identity (overrides client?as=),API_KEY-locked instance, accepts a valid token in place of the key — so end-users authenticate with their own IdP token instead of a shared secret.Zero(base, { token })sendsX-User-Token+?token=;client.me().Deferred (next step): row-level per-user authorization (own-your-rows ACL) built on this verified identity — kept out to keep this surface small and stable.
Verification
/v1/meecho + locked-mode authorization + invalid-token401; OIDC RS256 verified against a live JWKS endpoint withiss/audenforcement; and a JWTsubused as the trusted presence identity over a spoofed?as=./docs,.env.example, roadmap.https://claude.ai/code/session_018efxvWw3MRjdtvE5xgBqya
Generated by Claude Code