JSON Web Key (JWK) matching and selection

OpenID Connect servers as well as clients that use public key cryptography publish their JWKs in JSON format. The public JWKs are needed so that a counter party can obtain the key to validate a signed JWT or encrypt a JWT.

For example, a client that needs to verify an RSA-signed ID token needs to get the server’s JWK set and find matching public key candidates to validate the signature.

The following class is designed to help with that:

com.nimbusds.jose.jwk.JWKSelector

It supports key selection by:

  • Any, unspecified, one or more key types (kty).
  • Any, unspecified, one or more key uses (use).
  • Any, unspecified, one or more key operations (key_ops).
  • Any, unspecified, one or more key algorithms (alg).
  • Any, unspecified, one or more key identifiers (kid).
  • Private only key.
  • Public only key.
  • Minimum, maximum or exact key sizes (in bits).
  • Any, unspecified, one or more curves for EC keys (crv).

How to select an RSA public key that matches the key ID "123456":

import java.util.*;
import com.nimbusds.jose.jwk.*;

List<JWK> matches = new JWKSelector(
    new JWKMatcher.Builder()
        .keyType(KeyType.RSA)
        .keyID("123456")
        .build())
    .select(jwkSet);

System.out.println("Found " + matches.size() + " matching JWKs");

The JWK matching can also be performed by passing the JWS header of the received JOSE object or JWT. The forJWSHeader method will take the header's algorithm, key ID, etc to create the JWK matcher.

import java.util.*;
import com.nimbusds.jose.*;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jwt.*;

SignedJWT jwt = ...;
JWSHeader jwsHeader = jwt.getHeader();
List<JWK> matches = new JWKSelector(JWKMatcher.forJWSHeader(jwsHeader))
    .select(jwkSet);

System.out.println("Found " + matches.size() + " matching JWKs");

The complete configuration options of the JWK selector can be found in the JavaDocs.