Skip to content
Version v3.0.0

Client App Key Sets

ProAuth v3 stores client-owned public keys in first-class ClientAppKeySet records. A key set belongs to one client application and can be used by one or more security features through its usage flags.

Use key sets for public keys that ProAuth must trust when it validates something produced by the client, or for public encryption keys that ProAuth uses when it encrypts tokens for the client. Do not store client private keys in public key sets.

When To Configure A Key Set

FeatureConfigure a ClientAppKeySet?Required usage
private_key_jwt client authenticationYesClientAssertionSigning
JWT-secured authorization requests (JAR)YesRequestObjectSigning
self_signed_tls_client_authYesSelfSignedTlsClientAuth
Access token, ID token, UserInfo, or introspection response encryptionYesTokenEncryption
tls_client_auth with CA or ingress validated certificatesNoConfigure subject DN or SAN metadata on ClientAppAuthenticationConfiguration
Certificate-bound access tokensNo additional key setProAuth binds the access token to the certificate presented at the token endpoint
DPoP-bound access tokensNo static key setThe DPoP public key is sent in each DPoP proof and bound to the issued token

INFO

If the same public JWKS is intentionally used for more than one feature, use one key set with multiple usage flags. If different teams, deployments, rotation schedules, or trust boundaries own the keys, create separate key sets per usage.

Key Set Fields

Use the v2 Management API resource api/management/v2/ClientAppKeySet or the AdminApp key-set section of a client application.

FieldDescription
clientAppIdClient application that owns the key set.
nameHuman-readable name. Use names that identify the owner and purpose, for example portal-prod private_key_jwt.
descriptionOptional operational notes, such as certificate serial numbers or rotation ticket references.
sourceTypeOne of InlinePublicJwks, RemoteJwksUri, or InlineProtectedJwks.
usageOne or more key usages: ClientAssertionSigning, RequestObjectSigning, SelfSignedTlsClientAuth, TokenEncryption.
statusLifecycle state: Next, Active, Retiring, Retired, or Revoked.
jwksUriHTTPS URI for remote public JWKS sources.
jwksJsonInline public JWKS for signing, self-signed TLS client authentication, or asymmetric encryption.
protectedJwksJsonProtected inline JWKS for token encryption keys that must be protected at rest, including symmetric oct keys.
validFrom / validToOptional operational validity window. Runtime only uses key sets inside this window.
lastValidatedOn / lastValidationErrorDiagnostic validation metadata.

Runtime key resolution uses only key sets with status Active or Retiring and a currently valid time window. Next is useful for staging future configuration, but it is not used to validate signatures or encrypt tokens until it is changed to Active.

When one key set intentionally serves multiple features, provide a comma-separated usage value, for example ClientAssertionSigning, RequestObjectSigning.

Source Types

InlinePublicJwks

Use InlinePublicJwks when the public key material should be stored directly with the client configuration.

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\":\"portal-signing-2026-01\",\"use\":\"sig\",\"alg\":\"RS256\",\"n\":\"...\",\"e\":\"AQAB\"}]}"
}

Inline public JWKS may contain public RSA or EC keys. Signing and self_signed_tls_client_auth keys must be public asymmetric keys. Do not include private JWK members such as d, p, q, dp, dq, or qi.

RemoteJwksUri

Use RemoteJwksUri when the client publishes keys at a stable HTTPS endpoint.

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

Remote JWKS fetching is HTTPS-only, does not follow redirects, applies a short timeout and response-size limit, and rejects loopback, private, link-local, multicast, documentation, and reserved network targets. Publish old and new keys together during rotation so ProAuth can validate both kid values.

InlineProtectedJwks

Use InlineProtectedJwks only for token encryption keys that must be protected at rest.

json
{
  "name": "Resource server introspection response encryption key",
  "clientAppId": "10000000-0000-4000-8000-000000000020",
  "sourceType": "InlineProtectedJwks",
  "usage": "TokenEncryption",
  "status": "Active",
  "protectedJwksJson": "{\"keys\":[{\"kty\":\"oct\",\"kid\":\"rs-enc-2026-01\",\"use\":\"enc\",\"alg\":\"A256KW\",\"k\":\"...\"}]}"
}

Protected JWKS key sets are valid only with TokenEncryption. Symmetric JWE key wrapping algorithms such as A128KW and A256KW require this source type.

Rotation Guidance

Register more than one key during rotation. This avoids downtime for clients, distributed deployments, and cached remote JWKS documents.

Recommended rotation process for signing keys:

  1. Create the new key set as Next, or publish the new key in the existing remote JWKS while the key set remains Active.
  2. Change the new key set to Active before clients start signing with the new kid.
  3. Keep the old key set Active or Retiring until all old assertions, request objects, certificates, or encrypted responses can no longer be used.
  4. Change the old key set to Retired.
  5. Use Revoked only when the key must stop being trusted immediately.

For remote JWKS, prefer one stable URI per deployed application or resource server. During rotation, publish both keys at that URI. For inline JWKS, either add both keys to one key set or create a second key set with the same usage. Separate key sets are easier to audit when the old and new keys have different validity windows or owners.

For CLI-style or installed software clients, do not register every end-user installation unless the installation has a stable identity and lifecycle you can administer. For broad CLI distributions, prefer DPoP when the proof key is generated per token flow, or use a small number of managed confidential-client deployments with registered key sets for private_key_jwt, JAR, or token encryption.

YAML Import

In ProAuth CLI YAML imports, key sets are owned children of ClientApp. Use clientAppKeySets for long-lived configuration files. The shorter keySets alias is also accepted.

yaml
apiVersion: management.proauth.net/v2
kind: ClientApp
metadata:
  id: "{{guid:portal-client}}"
spec:
  subscriptionId: "{{guid:subscription}}"
  name: "Portal"
  enabled: true
  isPublic: false
  allowUserLogin: true
  clientAppKeySets:
    - id: "{{guid:portal-client-assertion-key}}"
      name: "Portal private_key_jwt signing keys"
      sourceType: InlinePublicJwks
      usage: ClientAssertionSigning
      status: Active
      jwksJson: '{"keys":[{"kty":"RSA","kid":"portal-signing-2026-01","use":"sig","alg":"RS256","n":"...","e":"AQAB"}]}'

For client authentication settings, create a separate ClientAppAuthenticationConfiguration resource and keep key material in clientAppKeySets:

yaml
apiVersion: management.proauth.net/v2
kind: ClientAppAuthenticationConfiguration
metadata:
  id: "{{guid:portal-client}}"
spec:
  tokenEndpointAuthMethod: private_key_jwt

The importer creates missing key sets and updates existing key sets by id. Omitting clientAppKeySets leaves existing key sets unchanged.