Configuration

MicroProfile JWT properties

Property Name Default Description

mp.jwt.verify.publickey

none

Public Key supplied as a string, parsed from it in the order defined in section Supported Public Key Formats.

mp.jwt.verify.publickey.location

none

Config property allows for an external or internal location of Public Key to be specified.

mp.jwt.verify.publickey.algorithm

RS256

Signature algorithm. Set it to ES256 to support the Elliptic Curve signature algorithm.

mp.jwt.decrypt.key.location

none

Config property allows for an external or internal location of Private Decryption Key to be specified.

mp.jwt.decrypt.key.algorithm

RSA-OAEP, RSA-OAEP-256

Decryption algorithm, both RSA-OAEP and RSA-OAEP-256 will be supported by default. Set it to RSA-OAEP-256 to support RSA-OAEP with SHA-256 only.

mp.jwt.verify.issuer

none

Expected value of the JWT iss (issuer) claim.

mp.jwt.verify.audiences

none

Comma separated list of the audiences that a token aud claim may contain.

mp.jwt.verify.clock.skew

60

Clock skew in seconds used during the token expiration and age verification. An expired token is accepted if the current time is within the number of seconds specified by this property after the token expiration time. The default value is 60 seconds.

mp.jwt.verify.token.age

none

Number of seconds that must not elapse since the iat (issued at) time.

mp.jwt.token.header

Authorization

Set this property if another header such as Cookie is used to pass the token.

mp.jwt.token.cookie

Bearer

Name of the cookie containing a token. This property will be effective only if mp.jwt.token.header is set to Cookie.

Supported Public Key Formats

Public Keys may be formatted in any of the following formats, specified in order of precedence:

  • Public Key Cryptography Standards #8 (PKCS#8) PEM

  • JSON Web Key (JWK) or JSON Web Key Set (JWKS)

  • Base64 URL encoded JSON Web Key (JWK) or JSON Web Key Set (JWKS)

SmallRye JWT properties

SmallRye JWT supports many properties which can be used to customize the token processing:

Property Name Default Description

smallrye.jwt.verify.key.location

NONE

Location of the verification key which can point to both public and secret keys. Secret keys can only be in the JWK format. Note that 'mp.jwt.verify.publickey.location' will be ignored if this property is set.

smallrye.jwt.verify.algorithm

RS256

Signature algorithm. Set it to ES256 to support the Elliptic Curve signature algorithm. This property is deprecated, use mp.jwt.verify.publickey.algorithm.

smallrye.jwt.verify.key-format

ANY

Set this property to a specific key format such as PEM_KEY, PEM_CERTIFICATE, JWK or JWK_BASE64URL to optimize the way the verification key is loaded.

smallrye.jwt.verify.relax-key-validation

false

Relax the validation of the verification keys, setting this property to true will allow public RSA keys with the length less than 2048 bit.

smallrye.jwt.verify.certificate-thumbprint

false

If this property is enabled then a signed token must contain either 'x5t' or 'x5t#S256' X509Certificate thumbprint headers. Verification keys can only be in JWK or PEM Certificate key formats in this case. JWK keys must have a 'x5c' (Base64-encoded X509Certificate) property set.

smallrye.jwt.token.header

Authorization

Set this property if another header such as Cookie is used to pass the token. This property is deprecated, use mp.jwt.token.header.

smallrye.jwt.token.cookie

none

Name of the cookie containing a token. This property will be effective only if smallrye.jwt.token.header is set to Cookie. This property is deprecated, use mp.jwt.token.cookie.

smallrye.jwt.always-check-authorization

false

Set this property to true for Authorization header be checked even if the smallrye.jwt.token.header is set to Cookie but no cookie with a smallrye.jwt.token.cookie name exists.

smallrye.jwt.token.schemes

Bearer

Comma-separated list containing an alternative single or multiple schemes, for example, DPoP.

smallrye.jwt.token.kid

none

Key identifier. If it is set then the verification JWK key as well every JWT token must have a matching kid header.

smallrye.jwt.time-to-live

none

The maximum number of seconds that a JWT may be issued for use. Effectively, the difference between the expiration date of the JWT and the issued at date must not exceed this value. Setting this property to a non-positive value relaxes the requirement for the token to have a valid 'iat' (issued at) claim.

smallrye.jwt.require.named-principal

false

If an application relies on java.security.Principal returning a name then a token must have a upn or preferred_username or sub claim set. Setting this property will result in SmallRye JWT throwing an exception if none of these claims is available for the application code to reliably deal with a non-null Principal name.

smallrye.jwt.path.sub

none

Path to the claim containing the subject name. It starts from the top level JSON object and can contain multiple segments where each segment represents a JSON object name only, example: realms/subject. This property can be used if a token has no 'sub' claim but has the subject set in a different claim. Use double quotes with the namespace qualified claims.

smallrye.jwt.claims.sub

none

This property can be used to set a default sub claim value when the current token has no standard or custom sub claim available. Effectively this property can be used to customize java.security.Principal name if no upn or preferred_username or sub claim is set.

smallrye.jwt.path.groups

none

Path to the claim containing the groups. It starts from the top level JSON object and can contain multiple segments where each segment represents a JSON object name only, example: realm/groups. This property can be used if a token has no 'groups' claim but has the groups set in a different claim. Use double quotes with the namespace qualified claims.

smallrye.jwt.groups-separator

' '

Separator for splitting a string which may contain multiple group values. It will only be used if the smallrye.jwt.path.groups property points to a custom claim whose value is a string. The default value is a single space because a standard OAuth2 scope claim may contain a space separated sequence.

smallrye.jwt.claims.groups

none

This property can be used to set a default groups claim value when the current token has no standard or custom groups claim available.

smallrye.jwt.jwks.refresh-interval

60

JWK cache refresh interval in minutes. It will be ignored unless the mp.jwt.verify.publickey.location points to the HTTP or HTTPS URL based JWK set and no HTTP Cache-Control response header with a positive max-age parameter value is returned from a JWK set endpoint.

smallrye.jwt.jwks.forced-refresh-interval

30

Forced JWK cache refresh interval in minutes which is used to restrict the frequency of the forced refresh attempts which may happen when the token verification fails due to the cache having no JWK key with a kid property matching the current token’s kid header. It will be ignored unless the mp.jwt.verify.publickey.location points to the HTTP or HTTPS URL based JWK set.

smallrye.jwt.expiration.grace

0

Expiration grace in seconds. By default an expired token will still be accepted if the current time is no more than 1 min after the token expiry time. This property is deprecated. Use mp.jwt.verify.clock.skew instead.

smallrye.jwt.verify.aud

none

Comma separated list of the audiences that a token aud claim may contain. This property is deprecated. Use mp.jwt.verify.audiences instead.

smallrye.jwt.required.claims

none

Comma separated list of the claims that a token must contain.

smallrye.jwt.decrypt.key.location

none

Config property allows for an external or internal location of Private Decryption Key to be specified. This property is deprecated, use mp.jwt.decrypt.key.location.

smallrye.jwt.decrypt.key

none

Decryption key supplied as a string.

smallrye.jwt.decrypt.algorithm

RSA_OAEP

Decryption algorithm. This property is deprecated, use mp.jwt.decrypt.key.algorithm.

smallrye.jwt.token.decryption.kid

none

Decryption Key identifier. If it is set then the decryption JWK key as well every JWT token must have a matching kid header.

smallrye.jwt.client.tls.certificate

none

TLS trusted certificate which may need to be configured if the keys have to be fetched over HTTPS. If this property is set then the smallrye.jwt.client.tls.certificate.path property will be ignored.

smallrye.jwt.client.tls.certificate.path

none

Path to TLS trusted certificate which may need to be configured if the keys have to be fetched over HTTPS. This property will be ignored if the smallrye.jwt.client.tls.certificate property is set.

smallrye.jwt.client.tls.trust-all

false

Trust all the hostnames. If the keys have to be fetched over HTTPS and this property is set to true then all the hostnames are trusted by default.

smallrye.jwt.client.tls.hosts

none

Set of trusted hostnames. If the keys have to be fetched over HTTPS and smallrye.jwt.client.tls.trust-all is set to false then then this property can be used to configure the trusted hostnames.

smallrye.jwt.http.proxy.host

none

HTTP proxy host.

smallrye.jwt.http.proxy.port

80

HTTP proxy port.

smallrye.jwt.keystore.type

JKS

This property can be used to customize a keystore type if either mp.jwt.verify.publickey.location or mp.jwt.decrypt.key.location` points to a KeyStore file. If it is not set then the file name will be checked to determine the keystore type before defaulting to JKS.

smallrye.jwt.keystore.provider

This property can be used to customize a KeyStore provider if mp.jwt.verify.publickey.location or mp.jwt.decrypt.key.location points to a KeyStore file.

smallrye.jwt.keystore.password

Keystore password. If mp.jwt.verify.publickey.location or mp.jwt.decrypt.key.location then this property has be set.

smallrye.jwt.keystore.verify.key.alias

This property has to be set to identify a public verification key which will be extracted from KeyStore from a matching certificate if mp.jwt.verify.publickey.location points to a KeyStore file.

smallrye.jwt.keystore.decrypt.key.alias

This property has to be set to identify a private decryption key if mp.jwt.decrypt.key.location points to a KeyStore file.

smallrye.jwt.keystore.decrypt.key.password

This property may be set if a private decryption key’s password in KeyStore is different to smallrye.jwt.keystore.password when mp.jwt.decrypt.key.location points to a KeyStore file.

Create JsonWebToken with JWTParser

If the JWT token can not be injected, for example, if it is embedded in the service request payload or the service endpoint acquires it out of band, then one can use JWTParser:

import org.eclipse.microprofile.jwt.JsonWebToken;
import io.smallrye.jwt.auth.principal.JWTParser;
...
@Inject JWTParser parser;

String token = getTokenFromOidcServer();

// Parse and verify the token
JsonWebToken jwt = parser.parse(token);

You can also use it to customize the way the token is verified or decrypted. For example, one can supply a local SecretKey:

import javax.crypto.SecretKey;
import javax.ws.rs.GET;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import org.eclipse.microprofile.jwt.JsonWebToken;
import io.smallrye.jwt.auth.principal.JWTParser;
import io.smallrye.jwt.build.Jwt;

@Path("/secured")
public class SecuredResource {
 @Inject JWTParser parser;
 private SecretKey key = createSecretKey();

 @GET
 @Produces("text/plain")
 public Response getUserName(@CookieParam("jwt") String jwtCookie) {
    Response response = null;
    if (jwtCookie == null) {
        String newJwtCookie = Jwt.upn("Alice").sign(key);
        // or newJwtCookie = Jwt.upn("alice").encrypt(key);
        return Response.ok("Alice").cookie(new NewCookie("jwt", newJwtCookie)).build();
    else {
        // All mp.jwt and smallrye.jwt properties are still effective, only the verification key is customized.
        JsonWebToken jwt = parser.verify(jwtCookie, key);
        // or jwt = parser.decrypt(jwtCookie, key);
        return Response.ok(jwt.getName()).build();
    }
}

Note that if you need to use JWTParser to verify the tokens with different verification constraints (for example, tokens have been signed by different providers, using different algorithms, etc) then please use a new instance of io.smallrye.jwt.auth.principal.DefaultJWTParser per every request - DefaultJWTParser has several methods for customizing the verification requirements.

If the same provider uses different keys to secure the token then using a JsonWebKey Set containing several keys may also work with the injected JWTParser.

Token Decryption

If your application needs to accept the tokens with the encrypted claims or with the encrypted inner signed claims then all you have to do is to set smallrye.jwt.decrypt.key-location pointing to the decryption key.

If this is the only key property which is set then the incoming token is expected to contain the encrypted claims only. If either mp.jwt.verify.publickey or mp.jwt.verify.publickey.location verification properties are also set then the incoming token is expected to contain the encrypted inner-signed token.

See Generate JWT tokens and learn how to generate the encrypted or inner-signed and then encrypted tokens fast.

Custom Factories

io.smallrye.jwt.auth.principal.DefaultJWTCallerPrincipalFactory is used by default to parse and verify JWT tokens and convert them to JsonWebToken principals. It uses MP JWT and smallrye-jwt properties listed in the Configuration section to verify and customize JWT tokens.

If you need to provide your own factory, for example, to avoid verifying the tokens again which have already been verified by the firewall, then you can either use a ServiceLoader mechanism by providing a META-INF/services/io.smallrye.jwt.auth.principal.JWTCallerPrincipalFactory resource or simply have an Alternative CDI bean implementation like this one:

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import javax.annotation.Priority;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Alternative;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;
import io.smallrye.jwt.auth.principal.DefaultJWTCallerPrincipal;
import io.smallrye.jwt.auth.principal.JWTAuthContextInfo;
import io.smallrye.jwt.auth.principal.JWTCallerPrincipal;
import io.smallrye.jwt.auth.principal.JWTCallerPrincipalFactory;
import io.smallrye.jwt.auth.principal.ParseException;

@ApplicationScoped
@Alternative
@Priority(1)
public class TestJWTCallerPrincipalFactory extends JWTCallerPrincipalFactory {

    @Override
    public JWTCallerPrincipal parse(String token, JWTAuthContextInfo authContextInfo) throws ParseException {
        try {
            // Token has already been verified, parse the token claims only
            String json = new String(Base64.getUrlDecoder().decode(token.split("\\.")[1]), StandardCharsets.UTF_8);
            return new DefaultJWTCallerPrincipal(JwtClaims.parse(json));
        } catch (InvalidJwtException ex) {
            throw new ParseException(ex.getMessage());
        }
    }
}