Private Key JWT: A Stronger Alternative for Client Authentication

If you're familiar with OAuth 2.0 and OpenID Connect, you know that client applications must authenticate themselves to the authorization server as part of a secure code-for-token exchange. This is necessary to verify the client's identity and ensure that only legitimate applications can receive the tokens from the authorization server.

Client authentication can be done in several ways, as defined in Open ID Connect Core Client Authentication. The most common approach to client authentication in traditional server-based applications is by using a client_secret: a shared password-like string. 

A more robust alternative method is Private Key JWT. With private_key_jwt,  client applications prove their identity by signing a JSON Web Token (JWT) with the private key of an asymmetric key pair. This signed JWT (client_assertion) is then sent to the authorization server for authentication. The server validates the signature using the client’s public key, accessible through a previously established registration or discovery mechanism. 

Private Key JWT client authentication is now a requirement for integrating with the Finnish Trust Network (FTN). However, this method is also fully supported and recommended for other eID integrations if your application is a confidential client.

FTN Security Requirements: What You Need to Know

The Finnish government is introducing new requirements to tighten authentication security of the Finnish Trust Network (FTN). The requirements are described in Recommendation 213/2023 S Finnish Trust Network OpenID Connect Profile and include:

  • Private Key JWT client authentication
  • Authentication request signing
  • Encrypted token and userinfo responses

We've just implemented these changes at Criipto and are sharing the details with you in this article series. The goal is to explain the main concepts and demonstrate how these requirements enhance the overall security of authentication flows.

If you're integrating with FTN, you have to understand and implement these changes. Even if FTN is not among the eIDs you currently use, we encourage you to familiarize yourself with these concepts: similar security measures might be adopted by other eIDs in the future, or you might simply gain a better understanding of modern authentication security.

The advantages of Private Key JWT authentication

Private Key JWT authentication offers several advantages over traditional client secrets.

1. Enhanced security against impersonation

Traditional client_secret authentication relies on a shared secret and symmetric cryptography. If the secret is leaked, intercepted, or stolen, anyone can impersonate your application, compromising its security. To make things worse, client secrets are usually long-lived and sent in plaintext over the wire. Therefore, if they happen to leak via e.g. shared HAR traces, the attacker will very likely be able to use them. 

Private Key JWT significantly reduces the attack surface for credential theft. It uses asymmetric cryptography: Your application keeps a private key to itself and shares only its corresponding public key with the authorization server. 

When authenticating, your application signs a JWT with its private key. The authorization server verifies the signature using your registered public key. So the private key never leaves your application, and the public key can’t be used to forge a signature and impersonate your application.

Private Key JWT also uses specific JWT claims (like jti for unique IDs and exp for expiration) to prevent replay attacks, ensuring each authentication attempt is valid only once.  Another security advantage is the shorter lifetime of the client_assertion—usually a maximum of an hour.

2. Stronger proof of origin and non-repudiation

Using client_secret for authentication makes it challenging to prove that a specific client application sent a specific request. In theory, anyone who has the secret could have sent it.

private_key_jwt authentication, on the other hand, offers much stronger proof that a specific client initiated a request. In this case, the client application's private key is never shared externally, so its security depends only on the key staying confidential. This eliminates security concerns about the authorization server's credential storage or any channel over which a client_secret might be sent.

That’s why the digital signature embedded in the client_assertion provides strong non-repudiation. The authorization server can cryptographically verify this signature using the corresponding public key, confirming that only that client could have signed the assertion. This cryptographic assurance means that when an action is logged, you almost certainly know which client performed it, creating a stronger, more reliable audit trail.

3. Simplified credential management 

Managing the full lifecycle of shared secrets—secure distribution, storage, and rotation—can be an operational and security burden.

With Private Key JWT, there's no client_secret to distribute or rotate. Your application simply generates an asymmetric key pair and registers its public key with the authorization server once. There are no secrets to transmit during registration and when authenticating with the authorization server. And if you decide to rotate your keys, your application simply regenerates its asymmetric key pair, replacing its private key and updating the public key registered with the authorization server. This process is inherently safer than replacing a symmetric client secret because no secrets are exchanged.

In summary 

Private Key JWT is a stronger standard for securing client authentication in sensitive environments. Its growing adoption in recent years is driven by evolving security standards (like those from the Financial-grade API (FAPI) Working Group), increased awareness of credential compromise risks, and various regulatory pushes, including eIDAS

You can start using Private Key JWT client authentication with Criipto by following this guide. If you have any questions, feel free to send an email to support@criipto.com or contact us on Slack.

 

Author

Latest blog posts

Private Key JWT: A Stronger Alternative for Client Authentication

If you're familiar with OAuth 2.0 and OpenID Connect, you know that client applications must authenticate themselves to the authorization server as...

Why Signed Authorization Requests Elevate Your Security

Signed authorization requests enhance the security of authentication flows and can be implemented as JWT-secured Authorization Requests (JARs). In...

Securing Authentication Flows with JSON Web Encryption

We previously covered the fundamentals of JSON Web Encryption (JWE), an IETF standard designed to keep data confidential. In today’s blog post, we’ll...

Sign up for our newsletter

Stay up to date on industry news and insights