Skip to content

docs(spec): verify the admin console session JWT against the service JWKS - #18

Draft
antstanley wants to merge 1 commit into
spec/own-outbound-http-boundaryfrom
spec/verify-admin-ui-session-jwt
Draft

docs(spec): verify the admin console session JWT against the service JWKS#18
antstanley wants to merge 1 commit into
spec/own-outbound-http-boundaryfrom
spec/verify-admin-ui-session-jwt

Conversation

@antstanley

@antstanley antstanley commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Note

Stacked PR 10 of 16 — part of stack #35, which targets main.
Base: #33 (spec/own-outbound-http-boundary) · Followed by: #26

This PR's diff shows only its own change. Merge the stack bottom-up; do not merge this before its base.

Why it sits at position 10: Declared prerequisite of #26: the admin plane cannot be hardened while the console still authorizes on an unverified JWT.

Scope of this PR

This PR currently carries the change spec. It will also carry the implementation plan and the build work for that spec — plan and code land as later commits on this same branch, so the spec, its plan, and its implementation review and merge as one unit.

Review order within the PR: spec first, then plan, then implementation.


Change spec proposing that the admin console verify the session JWT it authorizes on.

Problem. apps/admin-ui decodes the session cookie's JWT payload and trusts its claims without verifying the signature (hooks.server.ts), and the public POST /login action mints a session cookie from a caller-supplied JWT the same way (login/+page.server.ts). A hand-built {"sub":"x","role":"admin","exp":<future>} with arbitrary signature bytes is accepted, after which every request is made with INTERNAL_API_SECRET on the caller's behalf.

Proposed delta. Resolve key material through the existing GET /.well-known/openid-configurationjwks_uri surface and verify the JWS signature before any claim influences a decision, collapsing the session gate and the login action onto one verifyAccessToken helper and deleting decodeJwtPayload. Pin the algorithm to the discovery document, select by kid, require exp/iss/aud/sub to be present rather than merely correct when present, replace hasAdminClaim's String() coercion with an exact type-checked comparison, and set the cookie __Host-admin_session with secure/httpOnly/sameSite: strict. Every failure path is one fail-closed outcome: no session.

Notes.

  • getJwks already exists in src/lib/auth.ts with zero call sites — the verification primitive is present and dead.
  • Enforcing aud makes [token] audience a hard deployment prerequisite: the service issues aud: "" when it is unset (unwrap_or_default()). Recorded as an Assumption.
  • Whether apps/admin-ui is deployed anywhere is unresolved and recorded as an Open question; it is explicitly non-blocking for acceptance.

Drafted with the spec-creator plugin from a deep security scan of the repository at 53cbdec9. Spec only — no source changes.

@antstanley
antstanley force-pushed the spec/verify-admin-ui-session-jwt branch 2 times, most recently from 42ba77d to 1183460 Compare August 5, 2026 08:22
@antstanley
antstanley changed the base branch from main to spec/rotate-refresh-tokens August 5, 2026 08:22
@antstanley
antstanley marked this pull request as draft August 5, 2026 08:25
@antstanley
antstanley force-pushed the spec/verify-admin-ui-session-jwt branch from 1183460 to fd8765d Compare August 5, 2026 09:00
@antstanley
antstanley force-pushed the spec/verify-admin-ui-session-jwt branch from fd8765d to c6e42a8 Compare August 5, 2026 11:29
@antstanley
antstanley changed the base branch from spec/rotate-refresh-tokens to spec/own-outbound-http-boundary August 5, 2026 11:31
…JWKS

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@antstanley
antstanley force-pushed the spec/verify-admin-ui-session-jwt branch from c6e42a8 to 84211d2 Compare August 5, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant