Skip to content

Conversation

@arn-wlm
Copy link

@arn-wlm arn-wlm commented Dec 15, 2025

KAFKA-18608: feat: implement private_key_jwt client authentication for OAuth 2.0

Add support for RFC 7523 "private_key_jwt" client authentication method in OAuth Bearer token retrieval, providing an alternative to client_secret authentication using JWT assertions signed with private keys.

New Components

Core Implementation:

  • PrivateKeyJwtRetriever: Main JWT retriever implementing private_key_jwt client authentication using client_credentials grant type with JWT assertions
  • PrivateKeyRequestFormatter: HTTP request formatter for OAuth requests with client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
  • KidAssertionJwtTemplate: JWT template supporting 'kid' (Key ID) header for key identification in multi-key scenarios

Key Features:

  • Private key JWT assertion generation and signing
  • Support for RS256, RS384, RS512, ES256, ES384, ES512 algorithms
  • Optional client_id parameter support
  • Optional scope parameter support
  • Integration with existing HttpJwtRetriever infrastructure

Configuration

New SASL configuration options:

  • sasl.oauthbearer.client.credentials.client.id: Client identifier
  • sasl.oauthbearer.assertion.algorithm: JWT signing algorithm
  • sasl.oauthbearer.assertion.private.key.file: Private key file path
  • sasl.oauthbearer.assertion.private.key.passphrase: Optional passphrase

OAuth 2.0 Compliance

Implements RFC 7523 specification:

  • Uses grant_type=client_credentials
  • Uses client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
  • Generates RFC 7519 compliant JWT assertions with proper claims (iss, sub, aud, exp, iat, jti)

Differentiation from Existing Implementation

  • JwtBearerJwtRetriever: Uses grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer for service account authorization flows
  • PrivateKeyJwtRetriever: Uses grant_type=client_credentials with JWT assertions for client authentication (replaces client_secret with JWT)

Testing

Comprehensive test coverage:

  • PrivateKeyJwtRetrieverTest: 6 test cases covering configuration, error handling, and private key authentication flows
  • PrivateKeyRequestFormatterTest: 17 test cases including parameterized tests for URL encoding, optional parameters, and OAuth request formatting
  • All tests pass with proper Apache license headers and checkstyle compliance

Test scenarios include:

  • Valid configuration with required and optional parameters
  • Error handling for malformed private keys and invalid passphrases
  • Validation that static assertion files are not supported (ConfigException)
  • HTTP request formatting with proper OAuth 2.0 parameters
  • URL encoding of special characters in client_id and scope
  • Header formatting for OAuth token requests

Example Configuration

sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required ;
sasl.oauthbearer.jwt.retriever.class=org.apache.kafka.common.security.oauthbearer.PrivateKeyJwtRetriever
sasl.oauthbearer.client.credentials.client.id=my-service
sasl.oauthbearer.assertion.algorithm=RS256
sasl.oauthbearer.assertion.private.key.file=/path/to/private-key.pem
sasl.oauthbearer.token.endpoint.url=https://example.com/oauth2/token
sasl.oauthbearer.scope=kafka-access

Delete this text and replace it with a detailed description of your change. The 
PR title and body will become the squashed commit message.

If you would like to tag individuals, add some commentary, upload images, or
include other supplemental information that should not be part of the eventual
commit message, please use a separate comment.

If applicable, please include a summary of the testing strategy (including 
rationale) for the proposed change. Unit and/or integration tests are expected
for any behavior change and system tests should be considered for larger
changes.

@github-actions github-actions bot added triage PRs from the community clients labels Dec 15, 2025
@arn-wlm arn-wlm changed the title KAFKA-18608: feat: implement private_key_jwt client authentication fo… KAFKA-18608: feat: implement private_key_jwt client authentication for OAuth 2.0 Dec 15, 2025
…r OAuth 2.0

Add support for RFC 7523 "private_key_jwt" client authentication method
in OAuth Bearer token retrieval, providing an alternative to client_secret
authentication using JWT assertions signed with private keys.

## New Components

**Core Implementation:**
- `PrivateKeyJwtRetriever`: Main JWT retriever implementing private_key_jwt
  client authentication using client_credentials grant type with JWT assertions
- `PrivateKeyRequestFormatter`: HTTP request formatter for OAuth requests with
  client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
- `KidAssertionJwtTemplate`: JWT template supporting 'kid' (Key ID) header
  for key identification in multi-key scenarios

**Key Features:**
- Private key JWT assertion generation and signing
- Support for RS256, RS384, RS512, ES256, ES384, ES512 algorithms
- Optional client_id parameter support
- Optional scope parameter support
- Integration with existing HttpJwtRetriever infrastructure

## Configuration

New SASL configuration options:
- `sasl.oauthbearer.client.credentials.client.id`: Client identifier
- `sasl.oauthbearer.assertion.algorithm`: JWT signing algorithm
- `sasl.oauthbearer.assertion.private.key.file`: Private key file path
- `sasl.oauthbearer.assertion.private.key.passphrase`: Optional passphrase

## OAuth 2.0 Compliance

Implements RFC 7523 specification:
- Uses `grant_type=client_credentials`
- Uses `client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer`
- Generates RFC 7519 compliant JWT assertions with proper claims (iss, sub, aud, exp, iat, jti)

## Differentiation from Existing Implementation

- `JwtBearerJwtRetriever`: Uses `grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer`
  for service account authorization flows
- `PrivateKeyJwtRetriever`: Uses `grant_type=client_credentials` with JWT assertions
  for client authentication (replaces client_secret with JWT)

## Testing

**Comprehensive test coverage:**
- `PrivateKeyJwtRetrieverTest`: 6 test cases covering configuration, error handling,
  and private key authentication flows
- `PrivateKeyRequestFormatterTest`: 17 test cases including parameterized tests
  for URL encoding, optional parameters, and OAuth request formatting
- All tests pass with proper Apache license headers and checkstyle compliance

**Test scenarios include:**
- Valid configuration with required and optional parameters
- Error handling for malformed private keys and invalid passphrases
- Validation that static assertion files are not supported (ConfigException)
- HTTP request formatting with proper OAuth 2.0 parameters
- URL encoding of special characters in client_id and scope
- Header formatting for OAuth token requests

## Example Configuration

```properties
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required ;
sasl.oauthbearer.jwt.retriever.class=org.apache.kafka.common.security.oauthbearer.PrivateKeyJwtRetriever
sasl.oauthbearer.client.credentials.client.id=my-service
sasl.oauthbearer.assertion.algorithm=RS256
sasl.oauthbearer.assertion.private.key.file=/path/to/private-key.pem
sasl.oauthbearer.token.endpoint.url=https://example.com/oauth2/token
sasl.oauthbearer.scope=kafka-access
@arn-wlm arn-wlm force-pushed the features/private-key-jwt-retriever branch from c57e0bb to e1fe8e3 Compare December 15, 2025 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clients triage PRs from the community

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant