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
-
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>
-
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.
-
Add the
issuer
attribute. Enter a value for this attribute that matches the
iss
claim in the Java Web Token (JWT).
-
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.
-
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>
-
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>
-
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.
-
Configure a truststore file to include the JWK endpoint certificate so
that the Liberty server can make SSL
connections to the JWK endpoint.
-
Configure
truststores
on keystore
elements in the
server.xml
file.
-
Configure the SSL to reference this truststore file.
-
Set the SSL configuration as the server default SSL configuration or specify the
truststore
ID on the sslRef
attribute of the
mpJwt
element.
-
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.
- 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.
- 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;
}
- 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();
}
}
- 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.
- 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.
- 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.
- 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>
.
- 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.
- 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
:
- Create and name an
authFilter
. The following example is named
mpJwtAuthFilter
.<authFilter id="mpJwtAuthFilter">
<requestUrl id="myRequestUrl" urlPattern="/foo" matchType="contains"/>
</authFilter>
- In the
<mpJwt>
configuration element, add an authFilterRef
attribute that is set to the name of your authFilter
.
<mpJwt authFilterRef="mpJwtAuthFilter" ....>