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>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 {
}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@Claimannotation to оbtain the value of a claim by callinggetValue().
Configuration
Configuration options
| key | type | default value | description |
|---|---|---|---|
mp.jwt.verify.publickey | string | The property allows the Public Verification Key text itself to be supplied as a string. | |
mp.jwt.verify.publickey.location | string | 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.algorithm | string | 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 | |
mp.jwt.verify.issuer | string | Configuration key for expected issuer of incoming tokens. | |
mp.jwt.verify.audiences | string | Configuration key for expected audiences of incoming tokens. | |
mp.jwt.verify.token.age | int | Max number of seconds since token issue time. If this number of second accedes configured value, validation will fail. | |
mp.jwt.verify.clock.skew | int | Number of seconds for the clock skew during the token age verification and expiry. | |
mp.jwt.token.cookie | string | Cookie property name which is expected to contain a JWT token. | |
mp.jwt.token.header | string | Header name which is expected to contain a JWT token. | |
mp.jwt.decrypt.key.location | string | 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.algorithm | string | The configuration property allows for specifying which key management algorithm is supported by the MP JWT endpoint. Supported algorithms are either |
| key | type | default value | description |
|---|---|---|---|
optional | boolean | false | If set to |
authenticate | boolean | true | Whether to attempt authentication |
propagate | boolean | true | Whether to attempt identity propagation/JWT creation |
principal-type | string | USER | Whether we authenticate a user or a service (other option is SERVICE) |
atn-token | string | A group for configuring authentication of the request | |
atn-token.verify-signature | boolean | true | Whether to verify signature in incoming JWT. If disabled, ANY JWT will be accepted |
atn-token.jwt-audience | string | Expected audience of the JWT. If not defined, any audience is accepted (and we may accept JWT not inteded for us) | |
atn-token.jwk.resource | Resource | Configuration of the JWK to obtain key(s) to validate signatures of inbound token. The JWK should contain public keys. | |
atn-token.handler | string | Authorization header with `bearer ` prefix | A handler configuration for inbound token - e.g. how to extract it |
atn-token.handler.header | string | Name of a header the token is expected in | |
atn-token.handler.prefix | string | Prefix before the token value (optional) | |
atn-token.handler.regexp | string | Regular expression to obtain the token, first matching group is used (optional) | |
sign-token | string | A group for configuring outbound security | |
sign-token.jwk.resource | Resource | 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-issuer | string | When we issue a new token, this is the issuer to be placed into it (validated by target service) | |
sign-token.outbound | string | A group for configuring outbound rules (based on transport, host and.or path) | |
sign-token.outbound.*.name | string | A short descriptive name for configured target service(s) | |
sign-token.outbound.*.transports | string | any | An array of transports this outbound matches (e.g. https) |
sign-token.outbound.*.hosts | string | any | An array of hosts this outbound matches, may use * as a wild-card (e.g. *.oracle.com) |
sign-token.outbound.*.paths | string | any | An array of paths on the host this outbound matches, may use * as a wild-card (e.g. /some/path/*) |
sign-token.outbound.*.outbound-token | string | Authorization header with `bearer ` prefix | Configuration of outbound token handler (same as atn-token.handler) |
sign-token.outbound.*.outbound-token.format | string | Java text format for generating the value of outbound token header (e.g. "bearer %1$s") | |
sign-token.outbound.*.jwk-kid | string | 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-kid | string | 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-audience | string | 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-seconds | string | 5 | 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-seconds | string | 1 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/keysExamples
@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() + "!";
}
}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);
}
}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/keysObtain the Security Token from external issuer:
TOKEN=sdf4dDSWFcswdsffDSasEgv...Run the application and execute an http request against it:
curl -X GET -I -H "Authorization: Bearer $TOKEN" http://localhost:8080/helloHTTP/1.1 200 OK
Date: 08.06.2022 10:33:47 EEST
connection: keep-alive
content-length: 28
Hello, secure@helidon.io!which means that the request successfully passed authentication.
Additional Information
Learn more about JWT authentication at:
Eclipse MicroProfile Interoperable JWT RBAC