Configuring the MicroProfile JSON Web Token

You can configure a Liberty server to accept a MicroProfile JSON Web Token as an authentication token.

Before you begin

Install Java™ Platform, Standard Edition (Java SE) 8 or later to use the mpJwt-1.0 or mpJwt-1.1 feature.

About this task

MicroProfile JSON Web Token (MP-JWT) is a specification that defines the use of JWT as bearer token in a Microservices request Authorization: Bearer header defined by the RFC 6750 specification, The OAuth 2.0 Authorization Framework: Bearer Token Usage.

MP-JWT 1.0
MP-JWT 1.0 defines an interoperable token format and token access API, and consists of three parts:
  • The token format and claim
  • The org.eclipse.microprofile.jwt.JsonWebToken interface, a java.security.Principal interface extension that makes this set of claims available through get style accessors
  • Mapping of JSON Web Token and the claims to various Java EE container application programming interfaces (APIs)
With MP-JWT 1.0, any trusted party in possession of the MP-JWT token can use that token to access the associated resources in Liberty by sending the token over the authorization header. The token wire format must follow the RFC 6750 specification, as shown in the following example:
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Bearer <MP-JWT token>
See the MP-JWT 1.0 specification and API on GitHub at JWT RBAC for MicroProfile and in PDF format at Eclipse MicroProfile Interoperable JWT RBAC 1.1 specification.
MP-JWT 1.1
MP-JWT 1.1 defines portable JWT verification configuration that uses MicroProfile Config, and requires the support of JSON Web Key (JWK). See the MP-JWT-1.1 specification.
Liberty Complies with both MP-JWT 1.0 and 1.1. The Liberty resource server validates the MP-JWT token, creates the authenticated JSON Web Token, and makes the JSON Web Token and token claims available through CDI injection or JAX-RS security context. To be accepted as an MP-JWT token, the JWT token must contain a list of claims. The following example shows an MP-JWT token:
{
    "typ": "JWT",
    "alg": "RS256",
    "kid": "abc-1234567890"
}
{
       "iss": "https://server.example.com",
       "aud": "s6BhdRkqt3",
       "jti": "a-123",
       "exp": 1311281970,
       "iat": 1311280970,
       "sub": "24400320",
       "upn": "jdoe@server.example.com",
       "groups": ["red-group", "green-group", "admin-group", "admin"],
}

Procedure

  1. Add the mpJwt-1.0 or mpJwt-1.1 feature and any other necessary features to the server.xml file.
    At a minimum, the mpJwt-1.0 feature requires the jaxrs-2.0 feature.

    The mpJwt-1.1 feature includes mpJwt-1.0, and requires mpConfig-1.3 or the latest MicroProfile Config features. When mpJwt-1.1 is installed, mpConfig-1.3 is automatically installed.

    <featureManager>
        <feature>mpJwt-1.1</feature>
        <feature>jaxrs-2.0</feature>
        <feature>cdi-1.2</feature>
        ...
    </featureManager>
    
  2. Configure the mpJwt element. If you are using the mpJwt-1.0 feature, this step is required.

    If you are using the mpJwt-1.1 feature with a mpConfig-1.3 or later MicroProfile Config feature, this mpJwt configuration step is optional. Instead, you can use MP-JWT 1.1 properties to configure JWT validation. See step 3.

    1. Add the issuer attribute. Enter a value for this attribute that matches the iss claim in the Java Web Token (JWT).
    2. Add the audiences attribute if the JWT contains an aud claim. Enter a value for this attribute that contains one value of the aud claim in the JWT.
    3. Add the jwksUri attribute. Enter a value for this attribute that matches the URL for the JSON Web Key (JWK).
      The following code shows a typical mpJwt configuration element with JWK:
      <mpJwt 
           id="myMpJwt"
           jwksUri="https://example.com/api/jwk"
           issuer="https://example.com/api/v1"
           audiences="conferenceService">
      </mpJwt>
      
    4. Add the keyName attribute if you add the JWT signature validation key into the truststore file in the Secure Sockets Layer (SSL) configuration.
      The keyName attribute specifies the key alias in the truststore file.
      The following code shows a sample mpJwt configuration:
      <mpJwt 
           keyName="mpJwtValidationKey"
           issuer="https://example.com/api/v1"
           audiences ="conferenceService">
      </mpJwt>
      
  3. Configure MicroProfile Config for JWT validation. When you use the mpJwt-1.1 feature with a mpConfig-1.3 or later MicroProfile Config feature, you can configure JWT validation with the following three properties in the MP-JWT 1.1 specification.
    mp.jwt.verify.publickey
    Specifies the embedded key material of the public key for the MP-JWT signer in PKCS8 PEM or JWK(S) format. If not found, check the mp.jwt.verify.publickey.location value.
    mp.jwt.verify.publickey.location
    Specifies the relative path or full URL of the public key. All relative paths are resolved within the archive by using ClassLoader.getResource. If the value is a URL, the URL is resolved by using new URL("...").openStream().
    mp.jwt.verify.issuer
    Specifies the expected iss claim value to validate against an MP-JWT.
  4. Configure a truststore file to include the JWK endpoint certificate so that the Liberty server can make SSL connections to the JWK endpoint.
    1. Configure truststores on keystore elements in the server.xml file.
    2. Configure the SSL to reference this truststore file.
    3. Set the SSL configuration as the server default SSL configuration or specify the truststore ID on the sslRef attribute of the mpJwt element.
    4. If the JWT issuer does not support the JWK, and the JWT is signed with an X.509 certificate, import the X.509 certificate from the issuer into the truststore file in an SSL configuration.
  5. Optional: Define rules for mapping JWT claims to authentication subjects for a JWT that is not in MP-JWT format.
    By default, the program uses the upn claim as the principal name and unique security name of the user, and the program uses the groups claim as the group name for security role mapping. To change the default mapping, use the userNameAttribute attribute to choose a claim for the user principal, and use the groupNameAttribute attribute to choose a claim for the group name.
  6. Optional: Use the JAX-RS application to access the JsonWebToken getter by calling the API, javax.ws.rs.core.SecurityContext.getUserPrincipal().
    In the following example, the user principal is cast as an instance of the org.eclipse.microprofile.jwt.JsonWebToken API, and the application can access all claims through JsonWebToken getters:
    @GET
    @Path("/getGroups")
    public Set<String> getGroups(@Context SecurityContext sec) {
           Set<String> groups = null;
           Principal user = sec.getUserPrincipal();
           if (user instanceof JsonWebToken) {
                    JsonWebToken jwt = (JsonWebToken) user;
                    groups= = jwt.getGroups();
           }
           return groups;
    }
  7. Optional: Use a JAX-RS application to inject the org.eclipse.microprofile.jwt.JsonWebToken API through Raw Type, ClaimValue, javax.inject.Provider, and JSON-P types, as shown in the following example:
    @RequestScoped
    public class JwtEndpoint {
           @Inject
           private JsonWebToken jwtPrincipal;
           @GET
           @Path("/getInjectedPrincipal")
           public String getInjectedJWT() {
              return  this.jwtPrincipal.getName();
           }
    }
  8. Optional: If your program performs programmatic security, and you can get an org.eclipse.microprofile.jwt.JsonWebToken API from the subject, use the com.ibm.websphere.security.auth.WSSubject.getCallerPrincipal() API.
    In the current security context, the subject contains two java.security.Principal principals. One principal is the JSON Web Token.
  9. Optional: Secure JAX-RS resources with annotations and the group claims of the JWT. Map security role names that are used in the @RolesAllowed annotation to group names in the groups claim of the JWT.
    If the role name and group names are the same, you can omit the role mapping in the application-bnd element. However, if the JWT is an MP-JWT that contains group information, map in the application-bnd element to declare the role-to-group association. For more information, see Securing JAX-RS resources using annotations, Access IDs and authorization, and Authorization for applications when role mapping binding is not provided.
  10. Optional: Configure Liberty to check the user principal name from the JWT against the configured Liberty user registry.

    By default, the program creates a security subject from the verified JWT directly without the requirement of the user registry. To change this behavior, you add the mapToUserRegistry="true" configuration attribute in the server.xml file. The program searches the principal name against the configured user registry, and creates a security subject based on user attributes from the user registry.

  11. Optional: Configure Liberty to apply the mpJwt-1.0 feature only to applications that have a login method name of MP-JWT.
    By default, if the mpJwt-1.0 feature is configured, all authorized requests must include a valid JWT in the HTTP header. To modify the default behavior to require the JWT authentication token in some applications only, add the ignoreApplicationAuthMethod="false" configuration attribute to the <mpJwt> element in the server.xml file. Then, configure the application in one of two ways:
    • The application has an @LoginConfig annotation with the MP-JWT login method declared as the authentication method.

      For example, @LoginConfig(authMethod = "MP-JWT", realmName = "MP-JWT").

    • The web.xml file for the application has a declaration for the MP-JWT authentication method in the login-config element.

      For example, <login-config> <auth-method>MP-JWT</auth-method> <realm-name>MP-JWT</realm-name></login-config>.

  12. Optional: Configure Liberty to automatically propagate MP-JWT as an authentication token when Liberty calls other JAX-RS services.

    If Liberty is also acting as a JAX-RS 2.0 client, you add the authnToken="mpjwt" statement to the <webTarget> configuration element. The Liberty JAX-RS client then automatically adds JWT as an authorization header in the JAX-RS service call. For example, if you add the <webTarget uri="http://localhost:56789/protectedResourceWithMPJWT*" authnToken="mpjwt" /> element to the server.xml file, the JWT token is added to the authorization header when the http://localhost:56789/protectedResourceWithMPJWT/ service is called.

  13. Optional: Configure authentication filters.

    Liberty Security mpJwt-1.1 and mpJwt-1.0 are server-wide authentication mechanisms to override the application module login method. You can configure authFilter to limit mpJwt-1.x feature impact to the application login method. To limit an mpJwt-1.x feature for a subset of requests, configure your authFilter to define rules for the set of requests. Set the authFilterRef attribute in the <mpJwt...> element to the defined authFilter. For more information, see Authentication Filters.

    For example, to limit the mpJwt-1.1 feature to a request URL that contains /foo only, use an authFilter:
    1. Create and name an authFilter. The following example is named mpJwtAuthFilter.
      <authFilter id="mpJwtAuthFilter">
        <requestUrl id="myRequestUrl" urlPattern="/foo" matchType="contains"/>
      </authFilter>
    2. In the <mpJwt> configuration element, add an authFilterRef attribute that is set to the name of your authFilter.
      <mpJwt authFilterRef="mpJwtAuthFilter" ....>