Skip to content
Version v3.0.0

JWT Client Authentication

ProAuth supports JWT bearer client authentication for confidential clients using the OpenID Connect private_key_jwt and client_secret_jwt methods. These methods can be used at all ProAuth OAuth endpoints that require client authentication: token, introspection, revocation, device authorization, and pushed authorization request (PAR).

For FAPI 2.0 clients, use private_key_jwt; client_secret_jwt is not FAPI-compatible. See FAPI 2.0 Security Profile.

JWT client authentication is configured per client application with the tokenEndpointAuthMethod setting:

  • client_secret_basic
  • client_secret_post
  • client_secret_jwt
  • private_key_jwt
  • none

When a client application has an authentication configuration, ProAuth accepts only the configured method for that client. Existing clients without this configuration continue to use the legacy secret-based behavior.

Use the v2 Management API resource api/management/v2/ClientAppAuthenticationConfiguration to create or update this configuration. The request body uses these fields:

FieldDescription
clientAppIdClient application id that owns the authentication configuration.
tokenEndpointAuthMethodAuthentication method. Use private_key_jwt or client_secret_jwt for JWT client authentication.
requireCertificateBoundAccessTokensOptional token-binding flag. It may be enabled for non-mTLS methods, but the client must then present a valid certificate at the token endpoint so ProAuth can bind issued access tokens.

For private_key_jwt, configure the client's public signing keys as one or more Client App Key Sets with usage ClientAssertionSigning. Key material is not configured on ClientAppAuthenticationConfiguration in ProAuth v3.

Configure private_key_jwt

Use private_key_jwt when the client can keep a private signing key and ProAuth can validate assertions with the corresponding public key.

Configure two resources:

  1. A ClientAppAuthenticationConfiguration with tokenEndpointAuthMethod set to private_key_jwt.
  2. One or more ClientAppKeySet records with usage ClientAssertionSigning.

Example authentication configuration:

json
{
  "tokenEndpointAuthMethod": "private_key_jwt"
}

Example inline key set:

json
{
  "name": "Portal private_key_jwt signing keys",
  "clientAppId": "10000000-0000-4000-8000-000000000010",
  "sourceType": "InlinePublicJwks",
  "usage": "ClientAssertionSigning",
  "status": "Active",
  "jwksJson": "{\"keys\":[{\"kty\":\"RSA\",\"kid\":\"client-key-1\",\"use\":\"sig\",\"alg\":\"RS256\",\"n\":\"...\",\"e\":\"AQAB\"}]}"
}

Example remote key set:

json
{
  "name": "Portal remote private_key_jwt signing keys",
  "clientAppId": "10000000-0000-4000-8000-000000000010",
  "sourceType": "RemoteJwksUri",
  "usage": "ClientAssertionSigning",
  "status": "Active",
  "jwksUri": "https://client.example.com/.well-known/jwks.json"
}

Remote JWKS fetching is HTTPS-only. ProAuth resolves the host before fetching, does not follow redirects, enforces a short timeout and response-size cap, and rejects loopback, private, link-local, multicast, documentation, and reserved network targets.

The client signs each assertion with the private key. ProAuth validates the JWT header algorithm, kid, signature, issuer, subject, audience, expiration, and replay protection.

During key rotation, register both the old and new public keys. ProAuth selects by kid when the JWT header contains one, and active remote JWKS entries are refreshed when a kid is not found.

Configure client_secret_jwt

Use client_secret_jwt when the client and ProAuth share a client secret and the client signs assertions with HMAC.

json
{
  "tokenEndpointAuthMethod": "client_secret_jwt"
}

No JWKS source is allowed for this method. ProAuth validates the assertion with the active client secret.

Assertion Requirements

The request must include:

http
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
client_assertion=<signed JWT>

The JWT must contain:

  • iss: the client application id.
  • sub: the client application id.
  • aud: the exact endpoint URL being called, for example /connect/token, /connect/introspect, /connect/revoke, /connect/device, or /connect/par.
  • exp: a future expiration time.
  • jti: a unique assertion id.

The jti value is stored until the assertion expires and cannot be reused for the same client.

Example token request with private_key_jwt:

http
POST /connect/token HTTP/1.1
Host: idp.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&
client_id=00000000-0000-0000-0000-000000000000&
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&
client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6ImNsaWVudC1rZXktMSJ9...

Example token request with client_secret_jwt:

http
POST /connect/token HTTP/1.1
Host: idp.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&
client_id=00000000-0000-0000-0000-000000000000&
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&
client_assertion=eyJhbGciOiJIUzI1NiJ9...

Use the same request parameters at /connect/introspect, /connect/revoke, /connect/device, and /connect/par when those endpoints require client authentication. The assertion audience must be changed for each endpoint.

Client libraries fail closed for explicit secret-based methods. If ProAuth.Oidc.Client or ProAuth.Bff is configured with ClientSecretBasic, ClientSecretPost, or ClientSecretJwt, a client secret must be present. Use Auto only when the application intentionally allows public-client behavior when no secret is configured.

Discovery Metadata

Tenant discovery advertises client_secret_jwt and private_key_jwt in:

  • token_endpoint_auth_methods_supported
  • introspection_endpoint_auth_methods_supported
  • revocation_endpoint_auth_methods_supported

PAR support is advertised through pushed_authorization_request_endpoint; ProAuth applies the same configured client authentication method to PAR requests.