From 6404fa58ded6c979cd20ee748b5cde60f624a504 Mon Sep 17 00:00:00 2001 From: Sergey Beryozkin Date: Mon, 1 Nov 2021 14:21:55 +0000 Subject: [PATCH] Move Smallrye JWT Build docs to a separate guide --- .../src/main/asciidoc/security-jwt-build.adoc | 270 ++++++++++++++++ docs/src/main/asciidoc/security-jwt.adoc | 305 ++++++------------ ...ity-openid-connect-web-authentication.adoc | 1 + .../asciidoc/security-openid-connect.adoc | 2 + docs/src/main/asciidoc/security.adoc | 1 + .../resources/META-INF/quarkus-extension.yaml | 2 +- 6 files changed, 367 insertions(+), 214 deletions(-) create mode 100644 docs/src/main/asciidoc/security-jwt-build.adoc diff --git a/docs/src/main/asciidoc/security-jwt-build.adoc b/docs/src/main/asciidoc/security-jwt-build.adoc new file mode 100644 index 0000000000000..38bc26a6c22e5 --- /dev/null +++ b/docs/src/main/asciidoc/security-jwt-build.adoc @@ -0,0 +1,270 @@ +//// +This guide is maintained in the main Quarkus repository +and pull requests should be submitted there: +https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc +//// += Build, Sign and Encrypt JSON Web Tokens + +include::./attributes.adoc[] +:toc: + +According to link:https://datatracker.ietf.org/doc/html/rfc7519[RFC7519], JSON Web Token (JWT) is a compact, URL-safe means of representing claims which are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code(MAC) and/or encrypted. + +Signing the claims is used most often to secure the claims. What is known today as a JWT token is typically produced by signing the claims in a JSON format using the steps described in the link:https://tools.ietf.org/html/rfc7515[JSON Web Signature] specification. + +However, when the claims are sensitive, their confidentiality can be guaranteed by following the steps described in the link:https://tools.ietf.org/html/rfc7516[JSON Web Encryption] specification to produce a JWT token with the encrypted claims. + +Finally both the confidentiality and integrity of the claims can be further enforced by signing them first and then encrypting the nested JWT token. + +SmallRye JWT Build provides an API for securing JWT claims using all of these options. link:https://bitbucket.org/b_c/jose4j/wiki/Home[Jose4J] is used internally to support this API. + +== Maven dependency + +[source,xml] +---- + + io.quarkus + quarkus-smallrye-jwt-build + +---- + +Note you can use Smallrye JWT Build API without having to create Microprofile JWT endpoints supported by `quarkus-smallrye-jwt`. +It can also be excluded from `quarkus-smallrye-jwt` if MP JWT endpoints do not need to generate JWT tokens. + +== Create JwtClaimsBuilder and set the claims + +The first step is to initialize a `JwtClaimsBuilder` using one of the options below and add some claims to it: + +[source, java] +---- +import java.util.Collections; +import javax.json.Json; +import javax.json.JsonObject; +import io.smallrye.jwt.build.Jwt; +import io.smallrye.jwt.build.JwtClaimsBuilder; +import org.eclipse.microprofile.jwt.JsonWebToken; +... +// Create an empty builder and add some claims +JwtClaimsBuilder builder1 = Jwt.claims(); +builder1.claim("customClaim", "custom-value").issuer("https://issuer.org"); +// Or start typing the claims immediately: +// JwtClaimsBuilder builder1 = Jwt.upn("Alice"); + +// Builder created from the existing claims +JwtClaimsBuilder builder2 = Jwt.claims("/tokenClaims.json"); + +// Builder created from a map of claims +JwtClaimsBuilder builder3 = Jwt.claims(Collections.singletonMap("customClaim", "custom-value")); + +// Builder created from JsonObject +JsonObject userName = Json.createObjectBuilder().add("username", "Alice").build(); +JsonObject userAddress = Json.createObjectBuilder().add("city", "someCity").add("street", "someStreet").build(); +JsonObject json = Json.createObjectBuilder(userName).add("address", userAddress).build(); +JwtClaimsBuilder builder4 = Jwt.claims(json); + +// Builder created from JsonWebToken +@Inject JsonWebToken token; +JwtClaimsBuilder builder5 = Jwt.claims(token); +---- + +The API is fluent so the builder initialization can be done as part of the fluent API sequence. + +The builder will also set `iat` (issued at) to the current time, `exp` (expires at) to 5 minutes away from the current time (it can be customized with the `smallrye.jwt.new-token.lifespan` property) and `jti` (unique token identifier) claims if they have not already been set. + +One can also configure `smallrye.jwt.new-token.issuer` and `smallrye.jwt.new-token.audience` properties and skip setting the issuer and audience directly with the builder API. + +The next step is to decide how to secure the claims. + +[[sign-claims]] +== Sign the claims + +The claims can be signed immediately or after the `JSON Web Signature` headers have been set: + +[source, java] +---- +import io.smallrye.jwt.build.Jwt; +... + +// Sign the claims using an RSA private key loaded from the location set with a 'smallrye.jwt.sign.key.location' property. +// No 'jws()' transition is necessary. Default algorithm is RS256. +String jwt1 = Jwt.claims("/tokenClaims.json").sign(); + +// Set the headers and sign the claims with an RSA private key loaded in the code (the implementation of this method is omitted). +// Note a 'jws()' transition to a 'JwtSignatureBuilder', Default algorithm is RS256. +String jwt2 = Jwt.claims("/tokenClaims.json").jws().keyId("kid1").header("custom-header", "custom-value").sign(getPrivateKey()); +---- + +Note the `alg` (algorithm) header is set to `RS256` by default. Signing key identifier (`kid` header) does not have to be set if a single JSON Web Key (JWK) containing a `kid` property is used. + +RSA and Elliptic Curve (EC) private keys as well as symmetric secret keys can be used to sign the claims. +`ES256` and `HS256` are the defaut algorithms for EC private and symmetric key algorithms respectively. + +You can customize the signature algorithm, for example: + +[source, java] +---- +import io.smallrye.jwt.SignatureAlgorithm; +import io.smallrye.jwt.build.Jwt; + +// Sign the claims using an RSA private key loaded from the location set with a 'smallrye.jwt.sign.key.location' property. Algorithm is PS256. +String jwt = Jwt.upn("Alice").jws().algorithm(SignatureAlgorithm.PS256).sign(); +---- + +Note the `sign` step can be combined with the <> step to produce `inner-signed and encrypted` tokens, see <> section. + +[[encrypt-claims]] +== Encrypt the claims + +The claims can be encrypted immediately or after the `JSON Web Encryption` headers have been set the same way as they can be signed. +The only minor difference is that encrypting the claims always requires a `jwe()` `JwtEncryptionBuilder` transition given that the API has been optimized to support signing and inner-signing of the claims. + +[source, java] +---- +import io.smallrye.jwt.build.Jwt; +... + +// Encrypt the claims using an RSA public key loaded from the location set with a 'smallrye.jwt.encrypt.key.location' property. Default key encryption algorithm is RSA-OAEP. +String jwt1 = Jwt.claims("/tokenClaims.json").jwe().encrypt(); + +// Set the headers and encrypt the claims with an RSA public key loaded in the code (the implementation of this method is omitted). Default key encryption algorithm is A256KW. +String jwt2 = Jwt.claims("/tokenClaims.json").jwe().header("custom-header", "custom-value").encrypt(getSecretKey()); +---- + +Note the `alg` (key management algorithm) header is set to `RSA-OAEP` and the `enc` (content encryption header) is set to `A256GCM` by default. + +RSA and Elliptic Curve (EC) public keys as well as symmetric secret keys can be used to encrypt the claims. +`ECDH-ES` and `A256KW` are the defaut algorithms for EC public and symmetric key encryption algorithms respectively. + +Note two encryption operations are done when creating an ecrypted token: + +1) the generated content encryption key is encrypted by the key supplied with the API using the key encryption algorithm such as `RSA-OAEP` +2) the claims are encryped by the generated content encryption key using the content encryption algorithm such as `A256GCM`. + +You can customize the key and content encryption algorithms, for example: + +[source, java] +---- +import io.smallrye.jwt.KeyEncryptionAlgorithm; +import io.smallrye.jwt.ContentEncryptionAlgorithm; +import io.smallrye.jwt.build.Jwt; + +// Encrypt the claims using an RSA public key loaded from the location set with a 'smallrye.jwt.encrypt.key.location' property. +// Key encryption algorithm is RSA-OAEP-256, content encryption algorithm is A256CBC-HS512. +String jwt = Jwt.subject("Bob").jwe() + .keyAlgorithm(KeyEncryptionAlgorithm.RSA_OAEP_256) + .contentAlgorithm(ContentEncryptionAlgorithm.A256CBC_HS512) + .encrypt(); +---- + +Note that when the token is directly encrypted by the public RSA or EC key it is not possible to verify which party sent the token. +Therefore the secret keys should be preferred for directly encrypting the tokens, for example, when using JWT as cookies where a secret key is managed by the Quarkus endpoint with only this endpoint being both a producer and a consumer of the encrypted token. + +If you would like to use RSA or EC public keys to encrypt the token then it is recommended to sign the token first if the signing key is available, see the next <> section. + +[[innersign-encrypt-claims]] +== Sign the claims and encrypt the nested JWT token + +The claims can be signed and then the nested JWT token encrypted by combining the sign and encrypt steps. +[source, java] +---- +import io.smallrye.jwt.build.Jwt; +... + +// Sign the claims and encrypt the nested token using the private and public keys loaded from the locations set with the 'smallrye.jwt.sign.key.location' and 'smallrye.jwt.encrypt.key.location' properties respectively. +String jwt = Jwt.claims("/tokenClaims.json").innerSign().encrypt(); +---- + +== Fast JWT Generation + +If `smallrye.jwt.sign.key.location` or/and `smallrye.jwt.encrypt.key.location` properties are set then one can secure the existing claims (resources, maps, JsonObjects) with a single call: + +[source,java] +---- +// More compact than Jwt.claims("/claims.json").sign(); +Jwt.sign("/claims.json"); + +// More compact than Jwt.claims("/claims.json").jwe().encrypt(); +Jwt.encrypt("/claims.json"); + +// More compact than Jwt.claims("/claims.json").innerSign().encrypt(); +Jwt.signAndEncrypt("/claims.json"); +---- +As mentioned above, `iat` (issued at), `exp` (expires at), `jti` (token identifier), `iss` (issuer) and `aud` (audience) claims will be added if needed. + +== Dealing with the keys + +If you need to sign and/or encrypt the token using the symmetric secret key then consider using `io.smallrye.jwt.util.KeyUtils` to generate a SecretKey of the required length. + +For example, one needs to have a 64 byte key to sign using the `HS512` algorithm (`512/8`) and a 32 byte key to encrypt the content encryption key with the `A256KW` algorithm (`256/8`): + +```java +import javax.crypto.SecretKey; +import io.smallrye.jwt.KeyEncryptionAlgorithm; +import io.smallrye.jwt.SignatureAlgorithm; +import io.smallrye.jwt.build.Jwt; +import io.smallrye.jwt.util.KeyUtils; + +SecretKey signingKey = KeyUtils.generateSecretKey(SignatureAlgorithm.HS512); +SecretKey encryptionKey = KeyUtils.generateSecretKey(KeyEncryptionAlgorithm.A256KW); +String jwt = Jwt.claim("sensitiveClaim", getSensitiveClaim()).innerSign(signingKey).encrypt(encryptionKey); +``` + +You can also consider using a `JSON Web Key` (JWK) or `JSON Web Key Set` (JWK Set) format to store a secret key on a secure file system and refer to it using either `smallrye.jwt.sign.key.location` or `smallrye.jwt.encrypt.key.location` properties, for example: + +```json +{ + "kty":"oct", + "kid":"secretKey", + "k":"Fdh9u8rINxfivbrianbbVT1u232VQBZYKx1HGAGPt2I" +} +``` + +or + +```json +{ + "keys": [ + { + "kty":"oct", + "kid":"secretKey1", + "k":"Fdh9u8rINxfivbrianbbVT1u232VQBZYKx1HGAGPt2I" + }, + { + "kty":"oct", + "kid":"secretKey2", + "k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow" + } + ] +} +``` + +`io.smallrye.jwt.util.KeyUtils` can also be used to generate a pair of assymetric RSA or EC keys. These keys can be stored using a `JWK`, `JWK Set` or `PEM` format. + +== SmallRye JWT Builder configuration + +SmallRye JWT supports the following properties which can be used to customize the way claims are signed and/or encrypted: + +[cols="> for more information). +Often one obtains a JWT from an identity manager like https://www.keycloak.org/[Keycloak], but for this quickstart we will generate our own using the JWT generation API provided by `smallrye-jwt` (see link:smallrye-jwt-build[Generate JWT tokens with SmallRye JWT] for more information). Take the code from the following listing and place into `security-jwt-quickstart/src/main/java/org/acme/security/jwt/GenerateToken.java`: @@ -379,7 +381,7 @@ in order for the token to be accepted as valid. <2> The `upn` claim is defined by the {mp-jwt} spec as preferred claim to use for the `Principal` seen via the container security APIs. <3> The `group` claim provides the groups and top-level roles associated with the JWT bearer. -<4> The `birthday` claim. It can be considered to be a sensitive claim so you may want to consider encrypting the claims, see <>. +<4> The `birthday` claim. It can be considered to be a sensitive claim so you may want to consider encrypting the claims, see link:smallrye-jwt-build[Generate JWT tokens with SmallRye JWT]. Note for this code to work we need the content of the RSA private key that corresponds to the public key we have in the TokenSecuredResource application. Take the following PEM content and place it into `security-jwt-quickstart/src/test/resources/privateKey.pem`: @@ -456,7 +458,7 @@ eyJraWQiOiJcL3ByaXZhdGVLZXkucGVtIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiO The JWT string is the Base64 URL encoded string that has 3 parts separated by '.' characters. First part - JWT headers, second part - JWT claims, third part - JWT signature. -== Finally, Secured Access to /secured/roles-allowed +=== Finally, Secured Access to /secured/roles-allowed Now let's use this to make a secured request to the /secured/roles-allowed endpoint. Make sure you have the Quarkus server running using the `./mvnw compile quarkus:dev` command, and then run the following command, making sure to use your version of the generated JWT from the previous step: [source,bash] @@ -631,27 +633,7 @@ worked through in this quickstart guide as well as some additional endpoints tha of ``JsonWebToken``s and their claims into those using the CDI APIs. We suggest that you check out the quickstart solutions and explore the `security-jwt-quickstart` directory to learn more about the {extension-name} extension features. -[[configuration-reference]] -== Configuration Reference - -=== Quarkus configuration - -include::{generated-dir}/config/quarkus-smallrye-jwt.adoc[opts=optional, leveloffset=+1] - -=== MicroProfile JWT configuration - -[cols=">. -|mp.jwt.verify.publickey.location|none|Config property allows for an external or internal location of Public Key to be specified. The value may be a relative path or a URL. If the value points to an HTTPS based JWK set then, for it to work in native mode, the `quarkus.ssl.native` property must also be set to `true`, see link:native-and-ssl[Using SSL With Native Executables] for more details. -|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|Config property specifies the value of the `iss` (issuer) claim of the JWT that the server will accept as valid. -|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|none|Name of the cookie containing a token. This property will be effective only if `mp.jwt.token.header` is set to `Cookie`. -|=== +== Reference Guide === Supported Public Key Formats @@ -664,41 +646,30 @@ precedence: - JSON Web Key (JWK) Base64 URL encoded - JSON Web Key Set (JWKS) Base64 URL encoded -=== Additional SmallRye JWT configuration +=== Dealing with the verification keys -SmallRye JWT provides more properties which can be used to customize the token processing: +If you need to verify the token signature using the assymetric RSA or Elliptic Curve (EC) key then use the `mp.jwt.verify.publickey.location` property to refer to the local or remote verification key. -[cols="> and learn how to generate the encrypted or inner-signed and then encrypted tokens fast. - -== How to check the errors in the logs == - -Please enable `io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator` `TRACE` level logging to see more details about the token verification or decryption errors: - -[source, properties] ----- -quarkus.log.category."io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator".level=TRACE -quarkus.log.category."io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator".min-level=TRACE ----- +See link:smallrye-jwt-build[Generate JWT tokens with SmallRye JWT] and learn how to generate the encrypted or inner-signed and then encrypted tokens fast. -== Proactive Authentication - -If you'd like to skip the token verification when the public endpoint methods are invoked then please disable the link:security-built-in-authentication#proactive-authentication[proactive authentication]. - -Note that you can't access the injected `JsonWebToken` in the public methods if the token verification has not been done. - -== Custom Factories +=== Custom Factories `io.smallrye.jwt.auth.principal.DefaultJWTCallerPrincipalFactory` is used by default to parse and verify JWT tokens and convert them to `JsonWebToken` principals. It uses `MP JWT` and `smallrye-jwt` properties listed in the `Configuration` section to verify and customize JWT tokens. @@ -819,15 +774,15 @@ public class TestJWTCallerPrincipalFactory extends JWTCallerPrincipalFactory { } ---- -== Token Propagation +=== Token Propagation Please see link:security-openid-connect-client#token-propagation[Token Propagation] section about the Bearer access token propagation to the downstream services. [[integration-testing]] -== Testing +=== Testing [[integration-testing-wiremock]] -=== Wiremock +==== Wiremock If you configure `mp.jwt.verify.publickey.location` to point to HTTPS or HTTP based JsonWebKey (JWK) set then you can use the same approach as described in the link:security-openid-connect#integration-testing[OpenId Connect Bearer Token Integration testing] `Wiremock` section but only change the `application.properties` to use MP JWT configuration properties instead: @@ -842,7 +797,7 @@ smallrye.jwt.sign.key.location=privateKey.jwk ---- [[integration-testing-keycloak]] -=== Keycloak +==== Keycloak If you work with Keycloak and configure `mp.jwt.verify.publickey.location` to point to HTTPS or HTTP based JsonWebKey (JWK) set then you can use the same approach as described in the link:security-openid-connect#integration-testing-keycloak[OpenId Connect Bearer Token Integration testing] `Keycloak` section but only change the `application.properties` to use MP JWT configuration properties instead: @@ -854,7 +809,7 @@ mp.jwt.verify.issuer=${keycloak.url}/realms/quarkus ---- [[integration-testing-public-key]] -=== Local Public Key +==== Local Public Key You can use the same approach as described in the link:security-openid-connect#integration-testing[OpenId Connect Bearer Token Integration testing] `Local Public Key` section but only change the `application.properties` to use MP JWT configuration properties instead: @@ -869,7 +824,7 @@ smallrye.jwt.sign.key.location=privateKey.pem ---- [[integration-testing-security-annotation]] -=== TestSecurity annotation +==== TestSecurity annotation Add the following dependency: [source,xml] @@ -947,154 +902,76 @@ public class ProtectedResource { Note that `@TestSecurity` annotation must always be used and its `user` property is returned as `JsonWebToken.getName()` and `roles` property - as `JsonWebToken.getGroups()`. `@JwtSecurity` annotation is optional and can be used to set the additional token claims. -[[generate-jwt-tokens]] -== Generate JWT tokens with SmallRye JWT - -JWT claims can be signed or encrypted or signed first and the nested JWT token encrypted. -Signing the claims is used most often to secure the claims. What is known today as a JWT token is typically produced by signing the claims in a JSON format using the steps described in the link:https://tools.ietf.org/html/rfc7515[JSON Web Signature] specification. -However, when the claims are sensitive, their confidentiality can be guaranteed by following the steps described in the link:https://tools.ietf.org/html/rfc7516[JSON Web Encryption] specification to produce a JWT token with the encrypted claims. -Finally both the confidentiality and integrity of the claims can be further enforced by signing them first and then encrypting the nested JWT token. +=== How to check the errors in the logs -SmallRye JWT provides an API for securing the JWT claims using all of these options. - -=== Maven dependency - -[source,xml] ----- - - io.quarkus - quarkus-smallrye-jwt-build - ----- - -Note you can use Smallrye JWT Build API without having to create MP JWT endpoints. -It can also be excluded from `quarkus-smallrye-jwt` if MP JWT endpoints do not need to generate JWT tokens. - -=== Create JwtClaimsBuilder and set the claims - -The first step is to initialize a `JwtClaimsBuilder` using one of the options below and add some claims to it: - -[source, java] ----- -import java.util.Collections; -import javax.json.Json; -import javax.json.JsonObject; -import io.smallrye.jwt.build.Jwt; -import io.smallrye.jwt.build.JwtClaimsBuilder; -import org.eclipse.microprofile.jwt.JsonWebToken; -... -// Create an empty builder and add some claims -JwtClaimsBuilder builder1 = Jwt.claims(); -builder1.claim("customClaim", "custom-value").issuer("https://issuer.org"); -// Or start typing the claims immediately: -// JwtClaimsBuilder builder1 = Jwt.upn("Alice"); - -// Builder created from the existing claims -JwtClaimsBuilder builder2 = Jwt.claims("/tokenClaims.json"); - -// Builder created from a map of claims -JwtClaimsBuilder builder3 = Jwt.claims(Collections.singletonMap("customClaim", "custom-value")); - -// Builder created from JsonObject -JsonObject userName = Json.createObjectBuilder().add("username", "Alice").build(); -JsonObject userAddress = Json.createObjectBuilder().add("city", "someCity").add("street", "someStreet").build(); -JsonObject json = Json.createObjectBuilder(userName).add("address", userAddress).build(); -JwtClaimsBuilder builder4 = Jwt.claims(json); - -// Builder created from JsonWebToken -@Inject JsonWebToken token; -JwtClaimsBuilder builder5 = Jwt.claims(token); ----- - -The API is fluent so the builder initialization can be done as part of the fluent API sequence. - -The builder will also set `iat` (issued at) to the current time, `exp` (expires at) to 5 minutes away from the current time (it can be customized with the `smallrye.jwt.new-token.lifespan` property) and `jti` (unique token identifier) claims if they have not already been set. -One can also configure `smallrye.jwt.new-token.issuer` property and skip setting the issuer directly with the builder API. - -The next step is to decide how to secure the claims. - -=== Sign the claims - -The claims can be signed immediately or after the `JSON Web Signature` headers have been set: - -[source, java] ----- -import io.smallrye.jwt.build.Jwt; -... - -// Sign the claims using the private key loaded from the location set with a 'smallrye.jwt.sign.key.location' property. -// No 'jws()' transition is necessary. -String jwt1 = Jwt.claims("/tokenClaims.json").sign(); - -// Set the headers and sign the claims with an RSA private key loaded in the code (the implementation of this method is omitted). Note a 'jws()' transition to a 'JwtSignatureBuilder'. -String jwt2 = Jwt.claims("/tokenClaims.json").jws().keyId("kid1").header("custom-header", "custom-value").sign(getPrivateKey()); ----- - -Note the `alg` (algorithm) header is set to `RS256` by default and `keyId` (key identifier) does not have to be set if a single JSON Web Key (JWK) containing a `kid` property is used. - -=== Encrypt the claims - -The claims can be encrypted immediately or after the `JSON Web Encryption` headers have been set the same way as they can be signed. -The only minor difference is that encrypting the claims always requires a `jwe()` `JwtEncryptionBuilder` transition: +Please enable `io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator` `TRACE` level logging to see more details about the token verification or decryption errors: -[source, java] +[source, properties] ---- -import io.smallrye.jwt.build.Jwt; -... - -// Encrypt the claims using the public key loaded from the location set with a 'smallrye.jwt.encrypt.key.location' property. -String jwt1 = Jwt.claims("/tokenClaims.json").jwe().encrypt(); - -// Set the headers and encrypt the claims with an RSA public key loaded in the code (the implementation of this method is omitted). -String jwt2 = Jwt.claims("/tokenClaims.json").jwe().header("custom-header", "custom-value").encrypt(getPublicKey()); +quarkus.log.category."io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator".level=TRACE +quarkus.log.category."io.quarkus.smallrye.jwt.runtime.auth.MpJwtValidator".min-level=TRACE ---- -Note the `alg` (key management algorithm) header is set to `RSA-OAEP` and the `enc` (content encryption header) is set to `A256GCM` by default. +=== Proactive Authentication -=== Sign the claims and encrypt the nested JWT token - -The claims can be signed and then the nested JWT token encrypted by combining the sign and encrypt steps. -[source, java] ----- -import io.smallrye.jwt.build.Jwt; -... +If you'd like to skip the token verification when the public endpoint methods are invoked then please disable the link:security-built-in-authentication#proactive-authentication[proactive authentication]. -// Sign the claims and encrypt the nested token using the private and public keys loaded from the locations set with the 'smallrye.jwt.sign.key.location' and 'smallrye.jwt.encrypt.key.location' properties respectively. -String jwt = Jwt.claims("/tokenClaims.json").innerSign().encrypt(); ----- +Note that you can't access the injected `JsonWebToken` in the public methods if the token verification has not been done. -=== Fast JWT Generation +[[configuration-reference]] +== Configuration Reference -If `smallrye.jwt.sign.key.location` or/and `smallrye.jwt.encrypt.key.location` properties are set then one can secure the existing claims (resources, maps, JsonObjects) with a single call: +=== Quarkus configuration -[source,java] ----- -// More compact than Jwt.claims("/claims.json").sign(); -Jwt.sign("/claims.json"); +include::{generated-dir}/config/quarkus-smallrye-jwt.adoc[opts=optional, leveloffset=+1] -// More compact than Jwt.claims("/claims.json").jwe().encrypt(); -Jwt.encrypt("/claims.json"); +=== MicroProfile JWT configuration -// More compact than Jwt.claims("/claims.json").innerSign().encrypt(); -Jwt.signAndEncrypt("/claims.json"); ----- -As mentioned above, `iat`, `exp`, `jti` and `iss` claims will be added if needed. +[cols=">. +|mp.jwt.verify.publickey.location|none|Config property allows for an external or internal location of Public Key to be specified. The value may be a relative path or a URL. If the value points to an HTTPS based JWK set then, for it to work in native mode, the `quarkus.ssl.native` property must also be set to `true`, see link:native-and-ssl[Using SSL With Native Executables] for more details. +|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|Config property specifies the value of the `iss` (issuer) claim of the JWT that the server will accept as valid. +|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|none|Name of the cookie containing a token. This property will be effective only if `mp.jwt.token.header` is set to `Cookie`. +|=== -=== SmallRye JWT Builder configuration +=== Additional SmallRye JWT configuration -SmallRye JWT supports the following properties which can be used to customize the way claims are signed and encrypted: +SmallRye JWT provides more properties which can be used to customize the token processing: [cols="