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

KeyKindTypeDefault ValueDescription
mp.jwt.decrypt.key.algorithmVALUEi.h.m.j.a.J.j.d.k.algorithm Expected key management algorithm supported by the MP JWT endpoint
mp.jwt.decrypt.key.locationVALUEString Private key for decryption of encrypted claims
mp.jwt.token.cookieVALUEStringBearerSpecific cookie property name where we should search for JWT property
mp.jwt.token.headerVALUEStringAuthorizationName of the header expected to contain the token
mp.jwt.verify.audiencesLISTString Expected audiences of incoming tokens
mp.jwt.verify.clock.skewVALUEInteger5Clock skew to be accounted for in token expiration and max age validations in seconds
mp.jwt.verify.issuerVALUEString Expected issuer in incoming requests
mp.jwt.verify.publickeyVALUEString String representation of the public key
mp.jwt.verify.publickey.locationVALUEString Path to public key
mp.jwt.verify.token.ageVALUEInteger Maximal expected token age in seconds
security.providers.mp-jwt-auth.allow-impersonationVALUEBooleanfalseWhether to allow impersonation by explicitly overriding username from outbound requests using io.helidon.security.EndpointConfig#PROPERTY_OUTBOUND_ID property
security.providers.mp-jwt-auth.atn-token.default-key-idVALUEString Default JWT key ID which should be used
security.providers.mp-jwt-auth.atn-token.handlerVALUEi.h.s.u.TokenHandler Token handler to extract username from request
security.providers.mp-jwt-auth.atn-token.jwk.resourceVALUEi.h.c.c.Resource JWK resource for authenticating the request
security.providers.mp-jwt-auth.atn-token.jwt-audienceVALUEString Audience expected in inbound JWTs
security.providers.mp-jwt-auth.atn-token.verify-keyVALUEString Path to public key
security.providers.mp-jwt-auth.authenticateVALUEBooleantrueWhether to authenticate requests
security.providers.mp-jwt-auth.load-on-startupVALUEBooleanfalseWhether to load JWK verification keys on server startup Default value is false
security.providers.mp-jwt-auth.optionalVALUEBooleanfalseWhether authentication is required
security.providers.mp-jwt-auth.principal-typeVALUEi.h.s.SubjectTypeUSERPrincipal type this provider extracts (and also propagates)
security.providers.mp-jwt-auth.propagateVALUEBooleantrueWhether to propagate identity
security.providers.mp-jwt-auth.sign-tokenVALUEi.h.s.p.c.OutboundConfig Configuration of outbound rules

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