Contents

Overview

JSON Web Tokens (JWT) are an open, industry standard (RFC 7519) method for representing claims securely between two parties.

JSON Web Token defines a compact and self-contained way for securely transmitting information between parties as a JSON object. With JWT Auth you can integrate security features such as single sign on into your Helidon MP applications.

Maven Coordinates

To enable JWT Authentication either add a dependency on the helidon-microprofile bundle or add the following dependency to your project’s pom.xml (see Managing Dependencies).

<dependency>
    <groupId>io.helidon.microprofile.jwt</groupId>
    <artifactId>helidon-microprofile-jwt-auth</artifactId>
</dependency>
Copied

Usage

The main configuration point for JWT Auth is a JAX-RS Application class. As this class is discovered using CDI, it must have a bean defining annotation.

Minimal required setup is done using @LoginConfig(authMethod = "MP-JWT"):

@LoginConfig(authMethod = "MP-JWT")
@ApplicationScoped
public class ProtectedApplication extends Application {
}
Copied

API

The following interfaces and annotations are used to work with JWT in Helidon MP:

  • JsonWebToken - an interface used in CDI beans (@RequestScoped) dependency injection to obtain the JWT of the currently executing caller.

  • @Claim - an annotation used by CDI bean (@RequestScoped) dependency injection to obtain individual claims from the caller’s JWT.

  • ClaimValue - a proxy interface used with @Claim annotation to оbtain the value of a claim by calling getValue().

Configuration

Configuration options

MicroProfile configuration options:
keytypedefault valuedescription
mp.jwt.verify.publickeystring 

The property allows the Public Verification Key text itself to be supplied as a string.

mp.jwt.verify.publickey.locationstring 

The property allows for an external or internal location of Public Verification Key to be specified. The value may be a relative path or a URL.

mp.jwt.verify.publickey.algorithmstring 

The configuration property allows for specifying which Public Key Signature Algorithm is supported by the MP JWT endpoint. This property can be set to either RS256 or ES256. Default value is RS256. Support for the other asymmetric signature algorithms such as RS512, ES512 and others is optional.

mp.jwt.verify.issuerstring 

Configuration key for expected issuer of incoming tokens.

mp.jwt.verify.audiencesstring 

Configuration key for expected audiences of incoming tokens.

mp.jwt.verify.token.ageint 

Max number of seconds since token issue time. If this number of second accedes configured value, validation will fail.

mp.jwt.verify.clock.skewint 

Number of seconds for the clock skew during the token age verification and expiry.

mp.jwt.token.cookiestring 

Cookie property name which is expected to contain a JWT token.

mp.jwt.token.headerstring 

Header name which is expected to contain a JWT token.

mp.jwt.decrypt.key.locationstring 

The property allows for an external or internal location of Private Decryption Key to be specified. The value may be a relative path or a URL.

mp.jwt.decrypt.key.algorithmstring 

The configuration property allows for specifying which key management algorithm is supported by the MP JWT endpoint. Supported algorithms are either RSA-OAEP or RSA-OAEP-256. If no algorithm is set, both algorithms must be accepted.

Helidon configuration options:
keytypedefault valuedescription
optionalbooleanfalse

If set to true, failure to authenticate will return ABSTAIN result instead of FAILURE. This is an important distinction when more than one provider is used

authenticatebooleantrue

Whether to attempt authentication

propagatebooleantrue

Whether to attempt identity propagation/JWT creation

principal-typestringUSER

Whether we authenticate a user or a service (other option is SERVICE)

atn-tokenstring 

A group for configuring authentication of the request

atn-token.verify-signaturebooleantrue

Whether to verify signature in incoming JWT. If disabled, ANY JWT will be accepted

atn-token.jwt-audiencestring 

Expected audience of the JWT. If not defined, any audience is accepted (and we may accept JWT not inteded for us)

atn-token.jwk.resourceResource 

Configuration of the JWK to obtain key(s) to validate signatures of inbound token. The JWK should contain public keys.

atn-token.handlerstringAuthorization header with `bearer ` prefix

A handler configuration for inbound token - e.g. how to extract it

atn-token.handler.headerstring 

Name of a header the token is expected in

atn-token.handler.prefixstring 

Prefix before the token value (optional)

atn-token.handler.regexpstring 

Regular expression to obtain the token, first matching group is used (optional)

sign-tokenstring 

A group for configuring outbound security

sign-token.jwk.resourceResource 

Configuration of the JWK to use when generating tokens (follows the same rules as atn-token.jwk above). The JWK must contain private keys when using asymmetric ciphers.

sign-token.jwt-issuerstring 

When we issue a new token, this is the issuer to be placed into it (validated by target service)

sign-token.outboundstring 

A group for configuring outbound rules (based on transport, host and.or path)

sign-token.outbound.*.namestring 

A short descriptive name for configured target service(s)

sign-token.outbound.*.transportsstringany

An array of transports this outbound matches (e.g. https)

sign-token.outbound.*.hostsstringany

An array of hosts this outbound matches, may use * as a wild-card (e.g. *.oracle.com)

sign-token.outbound.*.pathsstringany

An array of paths on the host this outbound matches, may use * as a wild-card (e.g. /some/path/*)

sign-token.outbound.*.outbound-tokenstringAuthorization header with `bearer ` prefix

Configuration of outbound token handler (same as atn-token.handler)

sign-token.outbound.*.outbound-token.formatstring 

Java text format for generating the value of outbound token header (e.g. "bearer %1$s")

sign-token.outbound.*.jwk-kidstring 

If this key is defined, we are generating a new token, otherwise we propagate existing. Defines the key id of a key definition in the JWK file to use for signing the outbound token

sign-token.outbound.*.jwt-kidstring 

A key to use in the generated JWT - this is for the other service to locate the verification key in their JWK

sign-token.outbound.*.jwt-audiencestring 

Audience this key is generated for (e.g. http://www.example.org/api/myService) - validated by the other service

sign-token.outbound.*.jwt-not-before-secondsstring5

Makes this key valid this amount of seconds into the past. Allows a certain time-skew for the generated token to be valid before current time (e.g. when we expect a certain misalignment of clocks)

sign-token.outbound.*.jwt-validity-secondsstring1 day

Token validity in seconds

A configuration example in microprofile-config.properties:

mp.jwt.verify.issuer=https://{PublicIssuerDomain}/oauth2/default
mp.jwt.verify.publickey.location=${mp.jwt.verify.issuer}/v1/keys
Copied

Examples

@Path("/hello")
public class HelloResource {

    @GET
    @Produces(TEXT_PLAIN)
    public String hello(@Context SecurityContext context) {
        Optional<Principal> userPrincipal = context.userPrincipal();
        return "Hello, " + userPrincipal.get().getName() + "!";
    }
}
Copied

Do not forget to annotate the HelloApplication class to enable JWT:

@LoginConfig(authMethod = "MP-JWT")
@ApplicationScoped
public class HelloApplication extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        return Set.of(HelloResource.class);
    }
}
Copied

Add the following configuration in microprofile-config.properties:

mp.jwt.verify.issuer=https://{IssuerPublicDomain}/oauth2/default
mp.jwt.verify.publickey.location=${mp.jwt.verify.issuer}/v1/keys
Copied

Obtain the Security Token from external issuer:

TOKEN=sdf4dDSWFcswdsffDSasEgv...
Copied

Run the application and execute an http request against it:

curl -X GET -I -H "Authorization: Bearer $TOKEN" http://localhost:8080/hello
Copied
Curl output
HTTP/1.1 200 OK
Date: 08.06.2022 10:33:47 EEST
connection: keep-alive
content-length: 28

Hello, secure@helidon.io!
Copied

which means that the request successfully passed authentication.

Additional Information

Learn more about JWT authentication at:
Eclipse MicroProfile Interoperable JWT RBAC

Reference