fix(relay): address deep security review findings F1-F10
Critical fixes:
- F1: Add typ header discrimination between ES256 and HS256 tokens
- F2: Validate code_challenge_method is "S256" at token endpoint
- F10: Validate EC curve matches algorithm (P-256 for ES256)
Important fixes:
- F3: Reject refresh tokens with NULL jkt binding (treat as invalid_grant)
- F4: Add jti claim to AT+JWT access tokens (RFC 7519)
- F5: Add Cache-Control: no-store headers to token responses
- F6: Add cleanup functions for expired auth codes and refresh tokens
- F7: Validate code_verifier length (43-128 chars, unreserved charset)
- F8: Use constant-time comparison for jkt values (subtle::ConstantTimeEq)
- F9: Add ath claim validation at resource endpoints (RFC 9449 §4.3)
Implementation details:
- Updated OAuthSigningKey to include public_key_jwk for ES256 verification
- Added peek_jwt_typ helper for algorithm discrimination
- Split verify_access_token into ES256 and HS256 variants
- Added make_dpop_proof_with_iat_and_ath test helper for ath validation
- Updated all token response headers with Cache-Control headers
- Call cleanup functions on every token request for DB maintenance
- Updated test utilities to use valid 43-char code_verifier