Skip to content

Add RS256 signing support to common/jwt library #10898

@rapsealk

Description

@rapsealk

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

  • JWTSigner.generate_token() can sign with RS256 using an RSA private key
  • JWTValidator.validate_token() can validate RS256 tokens using an RSA public key
  • JWKS endpoint response can be parsed and keys looked up by kid
  • JWKS fetcher caches keys with configurable TTL and background refresh
  • RSA key pair can be generated programmatically (for dev/test)
  • kid header is included in RS256-signed JWTs
  • All existing HS256 tests continue to pass unchanged
  • pants lint/check/test pass with no new warnings

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions