Transform PoC to PassKey (WebAuthn) & JWT signing #2
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.
Implementation (or possible reference implementation) for https://github.com/nucypher/sprints/issues/273
Note: It is made with intensive usage of an LLM (Sonnet 4.5).
[UPDATE]
The code has been refactored at 1ebde9b so the JWT signing is detached from the passkey attestation. So the flow is to register JWT keys once and sign multiple JWTs without passkey interaction.
[INITIAL PR DESCRIPTION]
🔐 Passkey-Attested JWT Signing with Detached Signature Architecture
Summary
This PR implements a novel approach to JWT signing that combines the security benefits of hardware-backed passkeys with the efficiency and interoperability of standard JWTs. The key innovation is a detached signature architecture where passkeys attest JWT signing keys once during registration, enabling subsequent JWT signing operations without requiring passkey interaction.
Problem
Traditional JWT signing approaches face a trade-off:
Solution
This implementation introduces a two-phase approach:
Phase 1: Registration (One-Time)
Phase 2: Signing (Unlimited)
joselibraryKey Features
✅ Register once, sign many - After one-time registration, sign unlimited JWTs without passkey prompts
✅ Standard JWT format - Full compatibility with
jose.jwtVerify()and other JWT libraries✅ Hardware-backed security - JWT signing keys are cryptographically attested by passkeys
✅ Efficient verification - Two-stage process: standard JWT verify + DB authorization lookup
✅ Clean separation - Passkey attestation stored separately, not embedded in JWT payload
Architecture
Database Schema
Three core tables establish the trust chain:
credentials- Passkey credentials (WebAuthn)jwt_keys- JWT signing keys with passkey attestation (1:1 with passkeys)signatures- Audit trail of signed JWTsAPI Endpoints
POST /api/jwt-keys/registerGET /api/jwt-keys/:keyIdPOST /api/signPOST /api/validateTesting
44 comprehensive tests covering:
Tech Stack
Security Properties
From JWT Signing:
From Passkey Attestation:
From Architecture:
Usage Example
Files Changed
New Core Libraries:
src/lib/jwt-key-registration.ts- Key generation and fingerprintingsrc/lib/jwt-detached-verifier.ts- Two-stage verification logicAPI Routes:
src/app/api/jwt-keys/register/route.ts- Key registration endpointsrc/app/api/jwt-keys/[id]/route.ts- Key lookup endpointsrc/app/api/sign/route.tsandsrc/app/api/validate/route.tsDatabase:
src/lib/database.ts- Addedjwt_keystable and operationsTests:
src/__tests__/detached-signature.test.ts- Complete architecture testingDocumentation:
README.md- Comprehensive documentationFLOW.md- Detailed flow diagramsJWT-VERIFICATION-GUIDE.md- Integration guideThis implementation demonstrates how passkey security can be combined with JWT efficiency to create a practical authentication solution.