Summary
Extend the existing common/jwt library to support RS256 (asymmetric) signing alongside the current HS256, and add JWKS fetching/caching utilities — foundational for the OAuth2/OIDC Provider work.
Parent issue: #10500 (Phase 1, Step 1)
Motivation
The current common/jwt library only supports HS256 with per-user symmetric secrets. The OAuth2/OIDC Provider (Account Manager) needs RS256 asymmetric signing so that:
- Account Manager signs tokens with a private key
- Manager (and any resource server) validates tokens using the public key from a JWKS endpoint
- No shared secrets between services — only public keys distributed
Scope
Must have
JWTConfig: Add RS256 algorithm support, RSA key path configuration
JWTSigner: Sign JWTs with RSA private key (RS256)
JWTValidator: Validate JWTs with RSA public key (RS256)
JWTClaims: Add kid (key ID) field for key rotation
- JWKS utilities: Parse JWKS JSON, fetch from URL with caching, key lookup by
kid
- RSA key pair generation utility (for development/testing)
- All existing HS256 functionality unchanged (backward compatible)
- Full test coverage for RS256 sign/verify, JWKS parsing, key rotation, error cases
Out of scope
- Account Manager endpoints (separate issue)
- Manager middleware changes (separate issue)
- OAuth2 scope definitions (separate issue)
Key Files
| File |
Change |
src/ai/backend/common/jwt/config.py |
Add RS256 algorithm, key path fields |
src/ai/backend/common/jwt/signer.py |
RS256 signing with RSA private key |
src/ai/backend/common/jwt/validator.py |
RS256 validation with RSA public key |
src/ai/backend/common/jwt/types.py |
Add kid to JWTClaims |
New: src/ai/backend/common/jwt/jwks.py |
JWKS fetching, caching, key lookup |
New: src/ai/backend/common/jwt/keys.py |
RSA key pair generation, loading, serialization |
src/ai/backend/common/jwt/exceptions.py |
Add JWKS-related exceptions if needed |
src/ai/backend/common/jwt/__init__.py |
Export new public API |
| Tests |
RS256 round-trip, JWKS parsing, key rotation, HS256 backward compat |
Acceptance Criteria
Summary
Extend the existing
common/jwtlibrary to support RS256 (asymmetric) signing alongside the current HS256, and add JWKS fetching/caching utilities — foundational for the OAuth2/OIDC Provider work.Parent issue: #10500 (Phase 1, Step 1)
Motivation
The current
common/jwtlibrary only supports HS256 with per-user symmetric secrets. The OAuth2/OIDC Provider (Account Manager) needs RS256 asymmetric signing so that:Scope
Must have
JWTConfig: Add RS256 algorithm support, RSA key path configurationJWTSigner: Sign JWTs with RSA private key (RS256)JWTValidator: Validate JWTs with RSA public key (RS256)JWTClaims: Addkid(key ID) field for key rotationkidOut of scope
Key Files
src/ai/backend/common/jwt/config.pysrc/ai/backend/common/jwt/signer.pysrc/ai/backend/common/jwt/validator.pysrc/ai/backend/common/jwt/types.pykidto JWTClaimssrc/ai/backend/common/jwt/jwks.pysrc/ai/backend/common/jwt/keys.pysrc/ai/backend/common/jwt/exceptions.pysrc/ai/backend/common/jwt/__init__.pyAcceptance Criteria
JWTSigner.generate_token()can sign with RS256 using an RSA private keyJWTValidator.validate_token()can validate RS256 tokens using an RSA public keykidkidheader is included in RS256-signed JWTspants lint/check/testpass with no new warnings