code
Clone this repository
https://tangled.org/bretton.dev/coves
git@knot.bretton.dev:bretton.dev/coves
For self-hosted knots, clone URLs may differ based on your setup.
Add secp256k1 (ES256K) support to JWT access token verification using
Bluesky's indigo crypto package. This enables authentication from
external PDSes that use ES256K-signed tokens.
Changes:
- jwt.go: Add ES256K detection and verification using indigo's crypto
- New verifyES256KToken() for ES256K-specific verification
- New parseJWKMapToIndigoPublicKey() to convert JWK to indigo key
- New verifyJWTSignatureWithIndigoKey() for indigo signature verification
- New parseJWTClaimsManually() to parse claims without golang-jwt
- Update ToPublicKey() to return JWK map for secp256k1 curves
- did_key_fetcher.go: Return indigo PublicKey for secp256k1 keys
- FetchPublicKey now returns indigoCrypto.PublicKey for secp256k1
- NIST curves (P-256, P-384, P-521) still return *ecdsa.PublicKey
This complements the DPoP ES256K support added earlier, completing
full ES256K support across the authentication stack.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add ES256K (secp256k1) algorithm support using indigo's crypto package
- Add algorithm-curve binding validation to prevent algorithm confusion attacks
- Restore exp/nbf claim validation for DPoP proofs (security regression fix)
- Replace golang-jwt parsing with manual JWT parsing to support ES256K
- Add comprehensive test coverage for ES256K and security validations
- Update Caddyfile with proper Host headers for DPoP htu matching
Security fixes:
- Validate JWK curve matches claimed algorithm (ES256K->secp256k1, ES256->P-256, etc.)
- Validate exp claim if present (with clock skew tolerance)
- Validate nbf claim if present (with clock skew tolerance)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
DPoP security improvements addressing PR review findings:
- feat(auth): comprehensive DPoP security improvements
- Access token hash (ath) validation per RFC 9449
- Proxy header support (X-Forwarded-Host, RFC 7239 Forwarded)
- EscapedPath for percent-encoded URLs
- Case-insensitive DPoP scheme per RFC 7235
- fix(auth): prevent goroutine leak from DPoP replay cache
- Graceful server shutdown with signal handling
- Proper cleanup in integration tests
- docs: update authentication documentation for DPoP scheme
Add comment clarifying that PDS uploadBlob calls use Bearer scheme
(standard atproto server auth) rather than DPoP (AppView client auth).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update documentation to reflect the transition from Bearer tokens
to DPoP-bound tokens for client authentication:
- federation-prd.md: Update auth examples to use DPoP scheme
- Add note about Bearer vs DPoP for server-to-server auth
- Update request examples with DPoP header
- COMMENT_SYSTEM_IMPLEMENTATION.md: Update auth references
- "Bearer token" → "DPoP-bound access token"
- Document DPoP proof validation in OptionalAuth
- FEED_SYSTEM_IMPLEMENTATION.md: Update curl examples
- Add DPoP header alongside Authorization header
- Update auth requirement description
- PRD_OAUTH.md, aggregators/SETUP_GUIDE.md, auth/README.md:
- Minor terminology updates for consistency
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The DPoP verifier starts a background goroutine for nonce cache cleanup.
Without calling Stop(), this goroutine persists and accumulates across
server reloads and test runs.
Changes:
- cmd/server/main.go: Add graceful shutdown with signal handling
- Listen for SIGINT/SIGTERM
- Call authMiddleware.Stop() during shutdown
- Use http.Server.Shutdown() for graceful connection draining
- Integration tests: Add defer authMiddleware.Stop() after creation
- user_journey_e2e_test.go
- post_e2e_test.go
- community_e2e_test.go
- aggregator_e2e_test.go
- jwt_verification_test.go (2 locations)
This prevents NonceCache cleanup goroutines from leaking in both
production and test environments.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit addresses multiple security findings from PR review:
1. Access Token Hash (ath) Validation (RFC 9449 Section 4.2)
- Added VerifyAccessTokenHash() to verify DPoP proof's ath claim
- If ath is present, it MUST match SHA-256 hash of access token
- Prevents proof reuse across different tokens
2. Proxy Header Support for htu Verification
- Added extractSchemeAndHost() for X-Forwarded-Proto/Host support
- RFC 7239 Forwarded header parsing with mixed-case keys and quotes
- Critical for DPoP verification behind TLS-terminating proxies
3. Percent-Encoded Path Handling
- Use r.URL.EscapedPath() instead of r.URL.Path
- Preserves percent-encoding for accurate htu matching
4. Case-Insensitive DPoP Scheme (RFC 7235)
- Added extractDPoPToken() helper with strings.EqualFold()
- Accepts "DPoP", "dpop", "DPOP" per HTTP auth spec
Tests added for all security improvements:
- TestVerifyDPoPBinding_UsesForwardedHost
- TestVerifyDPoPBinding_UsesStandardForwardedHeader
- TestVerifyDPoPBinding_ForwardedMixedCaseAndQuotes
- TestVerifyDPoPBinding_AthValidation
- TestRequireAuth_CaseInsensitiveScheme
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The latest indigo (Nov 27, 2025) requires Go 1.25 which isn't available
in Docker Hub yet. Pin to the Oct 10, 2025 commit which is the last
Go 1.24-compatible version.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The local Go 1.25.1 is a pre-release version not available in Docker Hub.
Set minimum go version to 1.24 with toolchain directive for local dev.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement DPoP (RFC 9449) token binding for OAuth access tokens.
Features:
- DPoP proof verification with ES256 signing
- NonceCache for jti-based replay protection
- JWK thumbprint calculation per RFC 7638
- Middleware integration with Stop() for clean shutdown
- X-Forwarded-Proto support for reverse proxy deployments
Security:
- DPoP is additional security, never a fallback
- Tokens with cnf.jkt require valid DPoP proof
- 5-minute proof validity window
- Replay attack prevention via jti tracking
- Add github.com/google/uuid for DPoP proof jti generation
- Add .cache/ to .gitignore for Go build cache
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>