Skip to main content

private_key_jwt Client Authentication

Private_key_jwt is an OAuth 2.0 / OpenID Connect client authentication method where the client proves its identity by presenting a signed JWT "assertion" instead of a shared client secret. The authorization server validates this assertion using the client's registered public key and, if valid, treats the client as authenticated.

Concept and Positioning

Private_key_jwt is an asymmetric-key-based client authentication mechanism defined in OIDC Core and built on the JWT client assertion profile in RFC 7521 / RFC 7523. It is used at the token endpoint as a more secure alternative to client_secret_basic, client_secret_post. In high-security profiles like FAPI, private_key_jwt is either recommended or mandated for confidential clients.

Registration and Key Material

Before the flow can work, the client must be registered as a confidential client with its token endpoint authentication method set to private_key_jwt. The client generates an asymmetric key pair (for example, RSA or EC) and keeps the private key locally while publishing the corresponding public key to the AS, usually via:

  • A static JWK Set value (jwks) in dynamic or static client metadata.

  • A jwks_uri that the AS can dereference to obtain the client's JWK Set.

The AS associates these keys with the client_id and uses them to validate signatures on incoming assertions. Key rotation then consists of updating the registered JWK Set while the client switches to the new private key.

Assertion Structure and Claims

Client authentication is performed with a signed JWT sent as client_assertion and accompanied by client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer. The JWT header and payload have specific requirements presented below.

JOSE Header:

ClaimDescription
algA permitted asymmetric JWS algorithm (for example, RS256, PS256, ES256) negotiated at registration or constrained by server policy.
kidA key identifier that matches a JWK in the registered JWK Set when multiple keys exist.
typOften set to JWT (optional but common).

JWT Claims (Payload)

ClaimDescription
issThe client_id.
subThe client_id (same as iss for client auth).
audThe token endpoint URL (or the issuer/endpoint identifier required by the AS), preventing replay at other endpoints or servers.
jtiA unique identifier for this assertion instance, used by the AS to detect replays.
iatIssued-at timestamp (numeric date).
expExpiry timestamp, typically a short window (for example, 60–300 seconds after iat).

These semantics ensure that the assertion is bound to one client, to one audience, and to a narrow time window, and that individual assertions cannot be reused.

Token Endpoint Request Flow

In a typical authorization_code exchange with private_key_jwt, the client sends:

  • grant_type=authorization_code (or another supported grant).

  • The grant-specific parameters (code, redirect_uri, etc.).

  • Client assertion parameters:

    • client_id=<client_id>

    • client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer

    • client_assertion=<signed-JWT>

The assertion is usually signed using the client's private key on the local system or HSM, producing a compact JWS. The request body is application/x-www-form-urlencoded; the assertion itself is transmitted as an opaque string from the token endpoint's perspective.

Server-Side Validation Steps

On receipt, the authorization server performs an ordered set of checks:

  1. Syntactic checks

    • Parse the JWT.

    • Ensure required parameters (client_assertion, client_assertion_type, client_id) are present and consistent.

  2. Client and key resolution

    • Resolve the client configuration using client_id.

    • Verify that the configured token endpoint auth method is private_key_jwt.

    • Load the client's JWK Set from stored metadata or via jwks_uri.

    • Select the key by kid where present or by alg / key use when kid is omitted.

  3. Signature verification

    • Verify the JWS signature using the resolved public key.

    • Ensure the alg used is allowed for this client and endpoint.

  4. Claim validation

    • iss and sub match client_id.

    • aud matches the expected token endpoint or issuer identifier.

    • exp is in the future but within configured maximum assertion lifetime.

    • iat is within acceptable clock skew.

    • jti has not been seen before (usually via a replay cache keyed on client_id + jti within the assertion lifetime window).

  5. Replay protection and outcome

    • If any check fails, the server returns an OAuth error (for example, invalid_client or invalid_request).

    • If all checks pass, the client is considered authenticated, and normal token processing proceeds (authorization_code validation, scope checks, token issuance).

The replay cache can be implemented in-memory, distributed cache, or database, with expiration aligned to assertion lifetime; this is essential because the AS cannot rely solely on TLS to prevent capture and replay of an assertion.

Security Properties

Private_key_jwt has several useful properties in comparison to symmetric client secrets:

  • The client's private key is never sent over the wire; only the signed assertion is transmitted. Compromise of the AS database does not reveal the client's private key.

  • Public keys can be distributed and rotated without moving secret material, reducing risk during onboarding and rotation workflows.

  • Each authentication event is bound to a distinct signed object with jti, iat, and exp, yielding strong replay protection when combined with a replay cache.

  • Non-repudiation is stronger: a given assertion can be tied to a specific key controlled by the client, which is useful for regulated environments.

private_key_jwt Client Authentication to Raidiam APIs

Client applications registered in Raidiam Connect can be configured to use the private_key_jwt client authentication method to prove their identity to Connect's Authorization Server and obtain access tokens for Raidiam APIs.

When you register a client in Connect, the platform automatically:

  • Publishes a dedicated jwks_uri for that client

  • Registers the client at Raidiam's Authorization Server via Dynamic Client Registration (DCR), including the published jwks_uri in the registration

Whenever you generate or upload a signing key pair for your application, the public key is added to the client's JWKS document at the jwks_uri. This enables Raidiam's Authorization Server to retrieve the key and verify the signatures on your private_key_jwt client assertions.