Skip to content

Add verified JWT edge assertions via JWKS#52

Open
czpython wants to merge 11 commits into
commonzenpython/eng-730-edge-identity-headernone-door-cutover-onboarding-deployfrom
commonzenpython/eng-732-edge-identity-verified-jwt-edge-assertions-via-jwks-pr-3
Open

Add verified JWT edge assertions via JWKS#52
czpython wants to merge 11 commits into
commonzenpython/eng-730-edge-identity-headernone-door-cutover-onboarding-deployfrom
commonzenpython/eng-732-edge-identity-verified-jwt-edge-assertions-via-jwks-pr-3

Conversation

@czpython

Copy link
Copy Markdown
Owner

Third auth mode for the edge-identity arc: DRUKS_AUTH_MODE=jwt verifies an edge-signed assertion carried in DRUKS_AUTH_HEADER — RS256 against the edge's published JWKS (five-minute key cache, refetch on rotation), pinned iss/aud/exp, and the verified identity claim (default email) mapped through the same open-enrollment path header mode uses. Verification fails closed with a typed error naming only the failure class; the raw token never reaches an error or log. Bearer PATs still resolve first and the Authorization slot stays PAT-only.

Part of ENG-732 (edge-identity arc, PR 3 of 3; stacked on #51).

The pinned JWT profile (RS256, required iss/aud/exp, email claim) must be confirmed against the first real provider before the mode is enabled anywhere — tracked as the ticket's standing caveat.

🤖 Generated with Claude Code

czpython added 11 commits July 21, 2026 18:49
Close the stream only when identity actually fails to resolve; drop the
count helper the identity test can derive; pin that the session-era 404s
and /me set no cookie.
A stale unbound completion attaches to the operator the request resolved
instead of minting a rival none-mode account; the credential transaction
commits before the provider await so flushed row locks never span network
I/O; an identity recheck that resolves a different account broadcasts the
invalidation so account-scoped UI remounts.
Nothing past the credential commit may turn a durable connect into a
client-visible failure — the single-use flow is already spent. Refresh
trouble logs and rolls back its own transaction; the connect returns 200.
Materialize the response DTO before the commit expires the row and keep
rollback failures from escaping — after the point of durability the reply
depends on nothing but data already in hand.
Third auth mode: the edge signs its assertion and druks verifies it —
RS256 against the published JWKS (five-minute key cache, refetch on
rotation), pinned iss/aud/exp, identity claim mapped through the same
open enrollment. The PAT slot is untouched; PyJWT[crypto] is the one new
dependency.
Set-level key caching only (a per-kid cache trusts rotated-away keys
until restart); unknown kids get at most one forced refetch per trust
window; every verification failure — including transport surprises —
lands as the typed rejection; Authorization is refused as the identity
header; the test fakes stub the HTTP layer so the real cache runs.
Signature verification only trusts keys published for signing; the
forced-refresh stamp starts at -inf so a young monotonic clock cannot
suppress the first refetch; the fakes patch urllib.request.urlopen (the
symbol PyJWT actually calls) and the rotation test expires the real
cache instead of disabling its expiry.
Signing keys must pass both JWK restriction channels (use and key_ops);
assertion verification runs in the threadpool so a slow or dead JWKS
endpoint never stalls the event loop.
Absence is unrestricted; a present list permits exactly what it names
(RFC 7517), and malformed values permit nothing.
@czpython
czpython force-pushed the commonzenpython/eng-730-edge-identity-headernone-door-cutover-onboarding-deploy branch from 771d6aa to 8e9cad3 Compare July 21, 2026 21:02
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