[[MicroProfile_JWT_SmallRye]]
= MicroProfile JWT Subsystem

ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]

:auth-method: MicroProfile JWT

Support for https://microprofile.io/project/eclipse/microprofile-jwt-auth[MicroProfile JWT RBAC] is provided by the _microprofile-jwt-smallrye_ subsystem.

The MicroProfile JWT specification describes how authentication can be performed using cryptographically signed JWT tokens and the contents of the token to be used to establish a resuting identity without relying on access to external repositories of identities such as databases or directory servers.

[[subsystem-configuration-microprofile-jwt-smallrye]]
== Subsystem

The MicroProfile JWT integration is provided by the _microprofile-jwt-smallrye_ subsystem and is included in the default configuration, if not present the subsystem can be added using the following CLI commands.

[source,options="nowrap"]
----
[standalone@localhost:9990 /] /extension=org.wildfly.extension.microprofile.jwt-smallrye:add

[standalone@localhost:9990 /] /subsystem=microprofile-jwt-smallrye:add
----

At this point the server would need to be reloaded to activate the change.

== Configuration

The _microprofile-jwt-smallrye_ subsystem contains no configurable attributes or resources, it's presence is required however to detect if a deployment is making use of the MP-JWT authentication mechanism and to activate support for JWT making use of the https://github.com/smallrye/smallrye-jwt[SmallRye JWT] project.

=== Activation

The subsystem will scan all deployments to detect if the _MP-JWT_ mechanism is required for any web components and if true activate the integration and the authentication mechanism.

The classes in the deployment will be scanned to identify if there is a class which extends `jakarta.ws.rs.core.Application` annotated with the `org.eclipse.microprofile.auth.LoginConfig` to specify an _auth-method_.  Additionally the _auth-method_ contained within the deployments _web.xml_ will be checked.

If authentication configuration is defined within the `@LoginConfig` annotation and within the _web.xml_ deployment descriptor the contents of the web.xml are given precedence.

If after evaluating the deployment the resulting _auth-method_ is _MP-JWT_ then this integration will be activated, in all other cases no activation will occur and deployment will continue as normal.

=== MicroProfile Config

For an individual deployment the configuration in relation to MicroProfile JWT can be provided using MicroProfile Config properties, many are defined within the MicroProfile JWT specification however SmallRye JWT also supports some additional properties.

==== MicroProfile JWT properties

[cols="2,1,5"]
|===
|Property Name|Default|Description
|mp.jwt.verify.publickey|none|Public Key supplied as a string, parsed from it in the order defined in section https://smallrye.io/docs/smallrye-jwt/configuration.html#_supported_public_key_formats[Supported Public Key Formats].
|mp.jwt.verify.publickey.location|none|Config property allows for an external or internal location of Public Key to be specified.
|mp.jwt.verify.publickey.algorithm|`RS256`|Signature algorithm. Set it to `ES256` to support the Elliptic Curve signature algorithm.
|mp.jwt.decrypt.key.location|none|Config property allows for an external or internal location of Private Decryption Key to be specified.
|mp.jwt.verify.issuer|none|Expected value of the JWT `iss` (issuer) claim.
|mp.jwt.verify.audiences|`none`|Comma separated list of the audiences that a token `aud` claim may contain.
|mp.jwt.token.header|`Authorization`|Set this property if another header such as `Cookie` is used to pass the token.
|mp.jwt.token.cookie|`Bearer`|Name of the cookie containing a token. This property will be effective only if  `mp.jwt.token.header` is set to `Cookie`.
|===

A minimal `microprofile-config.properties` could look like: - 

[source,options="nowrap"]
----
mp.jwt.verify.publickey.location=META-INF/public.pem
mp.jwt.verify.issuer=quickstart-jwt-issuer
----

==== Unavailable Options

There are presently a couple of limitations with support for JWKS which we are looking to address.

 * If a JWKS is inlined using the `mp.jwt.verify.publickey` property then only the first key from the set will be used with the remainder being ignored.
 * Encoding of JWKS using Base64 is presently unsupported.
 
In both cases a clear text JWKS can be referenced instead using the `mp.jwt.verify.publickey.location` config property.

Support for Base64 encoded JWKS keys and inlined JWKS keys within the `mp.jwt.verify.publickey` property will be further evaluation and either support added or a contibution to the specification to remove these options.

==== SmallRye JWT Properties

The SmallRye JWT specific properties allow for a lot of customisation not covered by the specification, however as these are not specification defined they could be subject to change.

[cols="2,1,5"]
|===
|Property Name|Default|Description
|smallrye.jwt.verify.key.location|NONE|Location of the verification key which can point to both public and secret keys. Secret keys can only be in the JWK format. Note that 'mp.jwt.verify.publickey.location' will be ignored if this property is set.
|smallrye.jwt.verify.algorithm|`RS256`|Signature algorithm. Set it to `ES256` to support the Elliptic Curve signature algorithm. This property is deprecated, use `mp.jwt.verify.publickey.algorithm`.
|smallrye.jwt.verify.key-format|`ANY`|Set this property to a specific key format such as `PEM_KEY`, `PEM_CERTIFICATE`, `JWK` or `JWK_BASE64URL` to optimize the way the verification key is loaded.
|smallrye.jwt.verify.relax-key-validation|false|Relax the validation of the verification keys, setting this property to `true` will allow public RSA keys with the length less than 2048 bit.
|smallrye.jwt.verify.certificate-thumbprint|false|If this property is enabled then a signed token must contain either 'x5t' or 'x5t#S256' X509Certificate thumbprint headers. Verification keys can only be in JWK or PEM Certificate key formats in this case. JWK keys must have a 'x5c' (Base64-encoded X509Certificate) property set.
|smallrye.jwt.token.header|`Authorization`|Set this property if another header such as `Cookie` is used to pass the token. This property is deprecated, use `mp.jwt.token.header`.
|smallrye.jwt.token.cookie|none|Name of the cookie containing a token. This property will be effective only if  `smallrye.jwt.token.header` is set to `Cookie`. This property is deprecated, use `mp.jwt.token.cookie`.
|smallrye.jwt.always-check-authorization|false|Set this property to `true` for `Authorization` header be checked even if the `smallrye.jwt.token.header` is set to `Cookie` but no cookie with a `smallrye.jwt.token.cookie` name exists.
|smallrye.jwt.token.schemes|`Bearer`|Comma-separated list containing an alternative single or multiple schemes, for example, `DPoP`.
|smallrye.jwt.token.kid|none|Key identifier. If it is set then the verification JWK key as well every JWT token must have a matching `kid` header.
|smallrye.jwt.time-to-live|none|The maximum number of seconds that a JWT may be issued for use. Effectively, the difference between the expiration date of the JWT and the issued at date must not exceed this value.
|smallrye.jwt.require.named-principal|`false`|If an application relies on `java.security.Principal` returning a name then a token must have a `upn` or `preferred_username` or `sub` claim set. Setting this property will result in SmallRye JWT throwing an exception if none of these claims is available for the application code to reliably deal with a non-null `Principal` name.
|smallrye.jwt.path.sub|none|Path to the claim containing the subject name. It starts from the top level JSON object and can contain multiple segments where each segment represents a JSON object name only, example: `realms/subject`. This property can be used if a token has no 'sub' claim but has the subject set in a different claim. Use double quotes with the namespace qualified claims.
|smallrye.jwt.claims.sub|none| This property can be used to set a default sub claim value when the current token has no standard or custom `sub` claim available. Effectively this property can be used to customize `java.security.Principal` name if no `upn` or `preferred_username` or `sub` claim is set.
|smallrye.jwt.path.groups|none|Path to the claim containing the groups. It starts from the top level JSON object and can contain multiple segments where each segment represents a JSON object name only, example: `realm/groups`. This property can be used if a token has no 'groups' claim but has the groups set in a different claim. Use double quotes with the namespace qualified claims.
|smallrye.jwt.groups-separator|' '|Separator for splitting a string which may contain multiple group values. It will only be used if the `smallrye.jwt.path.groups` property points to a custom claim whose value is a string. The default value is a single space because a standard OAuth2 `scope` claim may contain a space separated sequence.
|smallrye.jwt.claims.groups|none| This property can be used to set a default groups claim value when the current token has no standard or custom groups claim available.
|smallrye.jwt.jwks.refresh-interval|60|JWK cache refresh interval in minutes. It will be ignored unless the `mp.jwt.verify.publickey.location` points to the HTTP or HTTPS URL based JWK set and no HTTP `Cache-Control` response header with a positive `max-age` parameter value is returned from a JWK set endpoint.
|smallrye.jwt.jwks.forced-refresh-interval|30|Forced JWK cache refresh interval in minutes which is used to restrict the frequency of the forced refresh attempts which may happen when the token verification fails due to the cache having no JWK key with a `kid` property matching the current token's `kid` header. It will be ignored unless the `mp.jwt.verify.publickey.location` points to the HTTP or HTTPS URL based JWK set.
|smallrye.jwt.expiration.grace|60|Expiration grace in seconds. By default an expired token will still be accepted if the current time is no more than 1 min after the token expiry time.
|smallrye.jwt.verify.aud|none|Comma separated list of the audiences that a token `aud` claim may contain. This property is deprecated. Use `mp.jwt.verify.audiences` instead.
|smallrye.jwt.required.claims|none|Comma separated list of the claims that a token must contain.
|smallrye.jwt.decrypt.key.location|none|Config property allows for an external or internal location of Private Decryption Key to be specified. This property is deprecated, use `mp.jwt.decrypt.key.location`.
|smallrye.jwt.decrypt.algorithm|`RSA_OAEP`|Decryption algorithm.
|smallrye.jwt.token.decryption.kid|none|Decryption Key identifier. If it is set then the decryption JWK key as well every JWT token must have a matching `kid` header.
|===


== Virtual Security

For traditional deployments to WildFly where security is required a security domain name would be identified during deployment and this in turn would be mapped to use configured resources either within the _elytron_ or legacy _security_ subsystems.

One of the main motivations for using MicroProfile JWT is the ability to describe an identity from the incoming token without relying on access to external resources.  For this reason MicroProfile JWT deployments will not depend on managed `SecurityDomain` resources, instead a virtual `SecurityDomain` will be created and used across the deployment.

As the deployment is configured entirely within the MicroProfile Config properties other than the presence of the _microprofile-jwt-smallrye_ subsystem the virtual `SecurityDomain` means no other managed configuration is required for the deployment.

[NOTE]
====
To propagate an identity from a virtual security domain, additional configuration might be required
depending on your use case. See <<Identity_Propagation, Identity Propagation>> for more details.
====
