diff --git a/src/main/java/io/jsonwebtoken/CompressionCodec.java b/src/main/java/io/jsonwebtoken/CompressionCodec.java index 35f038862..12264f224 100644 --- a/src/main/java/io/jsonwebtoken/CompressionCodec.java +++ b/src/main/java/io/jsonwebtoken/CompressionCodec.java @@ -16,31 +16,40 @@ package io.jsonwebtoken; /** - * Defines how to compress and decompress byte arrays. + * Compresses and decompresses byte arrays according to a compression algorithm. * - * @since 0.5.2 * @see io.jsonwebtoken.impl.compression.DeflateCompressionCodec * @see io.jsonwebtoken.impl.compression.GzipCompressionCodec + * @since 0.5.2 */ public interface CompressionCodec { /** - * The algorithm name that would appear in the JWT header. - * @return the algorithm name that would appear in the JWT header + * The algorithm name to use as the JWT's {@code calg} header value. + * + * @return the algorithm name to use as the JWT's {@code calg} header value. */ String getAlgorithmName(); /** - * Takes a byte array and returns a compressed version. + * Compresses the specified byte array according to the compression {@link #getAlgorithmName() algorithm}. + * * @param payload bytes to compress * @return compressed bytes + * @throws CompressionException if the specified byte array cannot be compressed according to the compression + * {@link #getAlgorithmName() algorithm}. */ - byte[] compress(byte[] payload); + byte[] compress(byte[] payload) throws CompressionException; /** - * Takes a compressed byte array and returns a decompressed version. + * Decompresses the specified compressed byte array according to the compression + * {@link #getAlgorithmName() algorithm}. The specified byte array must already be in compressed form + * according to the {@link #getAlgorithmName() algorithm}. + * * @param compressed compressed bytes * @return decompressed bytes + * @throws CompressionException if the specified byte array cannot be decompressed according to the compression + * {@link #getAlgorithmName() algorithm}. */ - byte[] decompress(byte[] compressed); + byte[] decompress(byte[] compressed) throws CompressionException; } \ No newline at end of file diff --git a/src/main/java/io/jsonwebtoken/CompressionCodecResolver.java b/src/main/java/io/jsonwebtoken/CompressionCodecResolver.java index 877ab8905..54d3c7fc5 100644 --- a/src/main/java/io/jsonwebtoken/CompressionCodecResolver.java +++ b/src/main/java/io/jsonwebtoken/CompressionCodecResolver.java @@ -16,16 +16,31 @@ package io.jsonwebtoken; /** - * Resolves "calg" header to an implementation of CompressionCodec. + * Looks for a JWT {@code calg} header, and if found, returns the corresponding {@link CompressionCodec} the parser + * can use to decompress the JWT body. + * + *

JJWT's default {@link JwtParser} implementation supports both the + * {@link io.jsonwebtoken.impl.compression.DeflateCompressionCodec DEFLATE} + * and {@link io.jsonwebtoken.impl.compression.GzipCompressionCodec GZIP} algorithms by default - you do not need to + * specify a {@code CompressionCodecResolver} in these cases.

+ * + *

However, if you want to use a compression algorithm other than {@code DEF} or {@code GZIP}, you must implement + * your own {@link CompressionCodecResolver} and specify that when + * {@link io.jsonwebtoken.JwtBuilder#compressWith(CompressionCodec) building} and + * {@link io.jsonwebtoken.JwtParser#setCompressionCodecResolver(CompressionCodecResolver) parsing} JWTs.

* * @since 0.5.2 */ public interface CompressionCodecResolver { + /** - * Examines the header and returns a CompressionCodec if it finds one that it recognizes. + * Looks for a JWT {@code calg} header, and if found, returns the corresponding {@link CompressionCodec} the parser + * can use to decompress the JWT body. + * * @param header of the JWT - * @return CompressionCodec matching the "calg" header, or null if there is no "calg" header. + * @return CompressionCodec matching the {@code calg} header, or null if there is no {@code calg} header. + * @throws CompressionException if a {@code calg} header value is found and not supported. */ - CompressionCodec resolveCompressionCodec(Header header); + CompressionCodec resolveCompressionCodec(Header header) throws CompressionException; } diff --git a/src/main/java/io/jsonwebtoken/JwtBuilder.java b/src/main/java/io/jsonwebtoken/JwtBuilder.java index b7985ef39..f88d2b0f3 100644 --- a/src/main/java/io/jsonwebtoken/JwtBuilder.java +++ b/src/main/java/io/jsonwebtoken/JwtBuilder.java @@ -350,10 +350,18 @@ public interface JwtBuilder extends ClaimsMutator { JwtBuilder signWith(SignatureAlgorithm alg, Key key); /** - * Compresses the JWT body using the {@link CompressionCodec} passed as argument. + * Compresses the JWT body using the specified {@link CompressionCodec}. * - * Note: Compression is not part of the Json Web Token specification and is not expected that other libraries (including - * older versions of this one) are able to consume a compressed JWT body correctly. + *

If your compact JWTs are large, and you want to reduce their total size during network transmission, this + * can be useful. For example, when embedding JWTs in URLs, some browsers may not support URLs longer than a + * certain length. Using compression can help ensure the compact JWT fits within that length. However, NOTE:

+ * + *

WARNING: Compression is not defined by the JWT Specification, and it is not expected that other libraries + * (including JJWT versions < 0.5.2) are able to consume a compressed JWT body correctly. Only use this method + * if you are sure that you will consume the JWT with JJWT >= 0.5.2 or another library that you know implements + * the same behavior.

+ * + * @see io.jsonwebtoken.impl.compression.CompressionCodecs * * @param codec implementation of the {@link CompressionCodec} to be used. * @return the builder for method chaining. diff --git a/src/main/java/io/jsonwebtoken/JwtParser.java b/src/main/java/io/jsonwebtoken/JwtParser.java index 5e5dcabdf..88daf131e 100644 --- a/src/main/java/io/jsonwebtoken/JwtParser.java +++ b/src/main/java/io/jsonwebtoken/JwtParser.java @@ -127,10 +127,10 @@ public interface JwtParser { /** * Sets the signing key used to verify any discovered JWS digital signature. If the specified JWT string is not * a JWS (no signature), this key is not used. - * + *

*

Note that this key MUST be a valid key for the signature algorithm found in the JWT header * (as the {@code alg} header parameter).

- * + *

*

This method overwrites any previously set key.

* * @param key the algorithm-specific signature verification key used to validate any discovered JWS digital @@ -142,12 +142,12 @@ public interface JwtParser { /** * Sets the signing key used to verify any discovered JWS digital signature. If the specified JWT string is not * a JWS (no signature), this key is not used. - * + *

*

Note that this key MUST be a valid key for the signature algorithm found in the JWT header * (as the {@code alg} header parameter).

- * + *

*

This method overwrites any previously set key.

- * + *

*

This is a convenience method: the string argument is first BASE64-decoded to a byte array and this resulting * byte array is used to invoke {@link #setSigningKey(byte[])}.

* @@ -160,12 +160,12 @@ public interface JwtParser { /** * Sets the signing key used to verify any discovered JWS digital signature. If the specified JWT string is not * a JWS (no signature), this key is not used. - * + *

*

Note that this key MUST be a valid key for the signature algorithm found in the JWT header * (as the {@code alg} header parameter).

- * + *

*

This method overwrites any previously set key.

- * + *

*

This is a convenience method: the string argument is first BASE64-decoded to a byte array and this resulting * byte array is used to invoke {@link #setSigningKey(byte[])}.

* @@ -178,12 +178,12 @@ public interface JwtParser { /** * Sets the {@link SigningKeyResolver} used to acquire the signing key that should be used to verify * a JWS's signature. If the parsed String is not a JWS (no signature), this resolver is not used. - * + *

*

Specifying a {@code SigningKeyResolver} is necessary when the signing key is not already known before parsing * the JWT and the JWT header or payload (plaintext body or Claims) must be inspected first to determine how to * look up the signing key. Once returned by the resolver, the JwtParser will then verify the JWS signature with the * returned key. For example:

- * + *

*

      * Jws<Claims> jws = Jwts.parser().setSigningKeyResolver(new SigningKeyResolverAdapter() {
      *         @Override
@@ -193,9 +193,9 @@ public interface JwtParser {
      *         }})
      *     .parseClaimsJws(compact);
      * 
- * + *

*

A {@code SigningKeyResolver} is invoked once during parsing before the signature is verified.

- * + *

*

This method should only be used if a signing key is not provided by the other {@code setSigningKey*} builder * methods.

* @@ -206,10 +206,22 @@ public interface JwtParser { JwtParser setSigningKeyResolver(SigningKeyResolver signingKeyResolver); /** - * Sets the {@link CompressionCodecResolver} used to acquire the {@link CompressionCodec} that should be used to verify - * a decompress the JWT body. If the parsed JWT is not compressed, this resolver si not used. - * - * @param compressionCodecResolver the compression codec resolver used to decompress the JWT body. + * Sets the {@link CompressionCodecResolver} used to acquire the {@link CompressionCodec} that should be used to + * decompress the JWT body. If the parsed JWT is not compressed, this resolver is not used. + *

NOTE: Compression is not defined by the JWT Specification, and it is not expected that other libraries + * (including JJWT versions < 0.5.2) are able to consume a compressed JWT body correctly. This method is only + * useful if the compact JWT was compressed with JJWT >= 0.5.2 or another library that you know implements + * the same behavior.

+ *
Default Support
+ *

JJWT's default {@link JwtParser} implementation supports both the + * {@link io.jsonwebtoken.impl.compression.DeflateCompressionCodec DEFLATE} + * and {@link io.jsonwebtoken.impl.compression.GzipCompressionCodec GZIP} algorithms by default - you do not need to + * specify a {@code CompressionCodecResolver} in these cases.

+ *

However, if you want to use a compression algorithm other than {@code DEF} or {@code GZIP}, you must implement + * your own {@link CompressionCodecResolver} and specify that via this method and also when + * {@link io.jsonwebtoken.JwtBuilder#compressWith(CompressionCodec) building} JWTs.

+ * + * @param compressionCodecResolver the compression codec resolver used to decompress the JWT body. * @return the parser for method chaining. * @since 0.5.2 */ @@ -218,7 +230,7 @@ public interface JwtParser { /** * Returns {@code true} if the specified JWT compact string represents a signed JWT (aka a 'JWS'), {@code false} * otherwise. - * + *

*

Note that if you are reasonably sure that the token is signed, it is more efficient to attempt to * parse the token (and catching exceptions if necessary) instead of calling this method first before parsing.

* @@ -231,7 +243,7 @@ public interface JwtParser { /** * Parses the specified compact serialized JWT string based on the builder's current configuration state and * returns the resulting JWT or JWS instance. - * + *

*

This method returns a JWT or JWS based on the parsed string. Because it may be cumbersome to determine if it * is a JWT or JWS, or if the body/payload is a Claims or String with {@code instanceof} checks, the * {@link #parse(String, JwtHandler) parse(String,JwtHandler)} method allows for a type-safe callback approach that @@ -258,11 +270,11 @@ public interface JwtParser { /** * Parses the specified compact serialized JWT string based on the builder's current configuration state and * invokes the specified {@code handler} with the resulting JWT or JWS instance. - * + *

*

If you are confident of the format of the JWT before parsing, you can create an anonymous subclass using the * {@link io.jsonwebtoken.JwtHandlerAdapter JwtHandlerAdapter} and override only the methods you know are relevant * for your use case(s), for example:

- * + *

*

      * String compactJwt = request.getParameter("jwt"); //we are confident this is a signed JWS
      *
@@ -273,10 +285,10 @@ public interface JwtParser {
      *     }
      * });
      * 
- * + *

*

If you know the JWT string can be only one type of JWT, then it is even easier to invoke one of the * following convenience methods instead of this one:

- * + *

*