diff --git a/CHANGELOG.md b/CHANGELOG.md index 7992227c0..621f4cd37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,7 +44,7 @@ AeadAlgorithm enc = Jwts.ENC.A256GCM; SecretKey key = enc.keyBuilder().build(); String compact = Jwts.builder().setSubject("Joe").encryptWith(key, enc).compact(); -Jwe jwe = Jwts.parserBuilder().decryptWith(key).build().parseClaimsJwe(compact); +Jwe jwe = Jwts.parser().decryptWith(key).build().parseClaimsJwe(compact); ``` Many other RSA and Elliptic Curve examples are in the full README documentation. @@ -179,8 +179,14 @@ deprecate some concepts, or in some cases, completely break backwards compatibil automatically based on builder state. -* `io.jsonwebtoken.Jwts`'s `parser()` method deprecated 4 years ago has been changed to now return a - `JwtParserBuilder` instead of a direct `JwtParser` instance. +* `io.jsonwebtoken.JwtParser` is now immutable. All mutation/modification methods (setters, etc) deprecated 4 years + ago have been removed. All parser configuration requires using the `JwtParserBuilder` (i.e. + `Jwts.parser()`). + + +* Similarly, `io.jsonwebtoken.Jwts`'s `parser()` method deprecated 4 years ago has been changed to now return a + `JwtParserBuilder` instead of a direct `JwtParser` instance. The previous `Jwts.parserBuilder()` method has been + removed as it is now redundant. * `io.jsonwebtoken.CompressionCodec` implementations are no longer discoverable via `java.util.ServiceLoader` due to diff --git a/README.md b/README.md index 70d2e1c75..1a08a672b 100644 --- a/README.md +++ b/README.md @@ -719,7 +719,7 @@ eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60A Now let's verify the JWT (you should always discard JWTs that don't match an expected signature): ```java -assert Jwts.parserBuilder().verifyWith(key).build().parseClaimsJws(jws).getPayload().getSubject().equals("Joe"); +assert Jwts.parser().verifyWith(key).build().parseClaimsJws(jws).getPayload().getSubject().equals("Joe"); ``` There are two things going on here. The `key` from before is being used to verify the signature of the JWT. If it @@ -737,7 +737,7 @@ But what if parsing or signature validation failed? You can catch `JwtException ```java try { - Jwts.parserBuilder().verifyWith(key).build().parseClaimsJws(compactJws); + Jwts.parser().verifyWith(key).build().parseClaimsJws(compactJws); //OK, we can trust this JWT @@ -957,7 +957,7 @@ String jws = Jwts.builder() .setExpiration(expiration) //a java.util.Date .setNotBefore(notBefore) //a java.util.Date .setIssuedAt(new Date()) // for example, now - .setId(UUID.randomUUID()) //just an example id + .setId(UUID.randomUUID().toString()) //just an example id /// ... etc ... ``` @@ -1047,7 +1047,7 @@ Please see the main [Compression](#compression) section to see how to compress a You read (parse) a JWT as follows: -1. Use the `Jwts.parserBuilder()` method to create a `JwtParserBuilder` instance. +1. Use the `Jwts.parser()` method to create a `JwtParserBuilder` instance. 2. Optionally call `setKeyLocator`, `verifyWith` or `decryptWith` methods if you expect to parse [signed](#jws) or [encrypted](#jwe) JWTs. 3. Call the `build()` method on the `JwtParserBuilder` to create and return a thread-safe `JwtParser`. 4. Call one of the various `parse*` methods with your compact JWT string, depending on the type of JWT you expect. @@ -1059,7 +1059,7 @@ For example: Jwt jwt; try { - jwt = Jwts.parserBuilder() // (1) + jwt = Jwts.parser() // (1) .setKeyLocator(keyLocator) // (2) dynamically locate signing or encryption keys //.verifyWith(key) // or a static key used to verify all signed JWTs @@ -1099,7 +1099,7 @@ So which key do we use? `JwtParserBuilder`. For example: ```java - Jwts.parserBuilder() + Jwts.parser() .verifyWith(secretKey) // <---- @@ -1110,7 +1110,7 @@ So which key do we use? `PrivateKey`) should be specified on the `JwtParserBuilder`. For example: ```java - Jwts.parserBuilder() + Jwts.parser() .verifyWith(publicKey) // <---- publicKey, not privateKey @@ -1121,7 +1121,7 @@ So which key do we use? specified on the `JwtParserBuilder`. For example: ```java - Jwts.parserBuilder() + Jwts.parser() .decryptWith(secretKey) // <---- @@ -1132,7 +1132,7 @@ So which key do we use? `PrivateKey` (not the `PublicKey`) should be specified on the `JwtParserBuilder`. For example: ```java - Jwts.parserBuilder() + Jwts.parser() .decryptWith(privateKey) // <---- privateKey, not publicKey @@ -1172,7 +1172,7 @@ example: ```java Locator keyLocator = getMyKeyLocator(); -Jwts.parserBuilder() +Jwts.parser() .setKeyLocator(keyLocator) // <---- @@ -1214,10 +1214,10 @@ String keyId = getKeyId(key); //any mechanism you have to associate a key with a String jws = Jwts.builder() - .setHeader(Jwts.headerBuilder().setKeyId(keyId)) // <--- add `kid` header + .header().setKeyId(keyId).and() // <--- add `kid` header - .signWith(key) // for JWS - //.encryptWith(key, keyAlg, encryptionAlg) // for JWE + .signWith(key) // for JWS + //.encryptWith(key, keyAlg, encryptionAlg) // for JWE .compact(); ``` @@ -1300,7 +1300,7 @@ otherwise you may not trust the token. You can do that by using one of the vari ```java try { - Jwts.parserBuilder().requireSubject("jsmith")/* etc... */.build().parse(s); + Jwts.parser().requireSubject("jsmith")/* etc... */.build().parse(s); } catch (InvalidClaimException ice) { // the sub field was missing or did not have a 'jsmith' value } @@ -1311,7 +1311,7 @@ you can catch either `MissingClaimException` or `IncorrectClaimException`: ```java try { - Jwts.parserBuilder().requireSubject("jsmith")/* etc... */.build().parse(s); + Jwts.parser().requireSubject("jsmith")/* etc... */.build().parse(s); } catch(MissingClaimException mce) { // the parsed JWT did not have the sub field } catch(IncorrectClaimException ice) { @@ -1323,7 +1323,7 @@ You can also require custom fields by using the `require(fieldName, requiredFiel ```java try { - Jwts.parserBuilder().require("myfield", "myRequiredValue")/* etc... */.build().parse(s); + Jwts.parser().require("myfield", "myRequiredValue")/* etc... */.build().parse(s); } catch(InvalidClaimException ice) { // the 'myfield' field was missing or did not have a 'myRequiredValue' value } @@ -1347,7 +1347,7 @@ You can account for these differences (usually no more than a few minutes) when ```java long seconds = 3 * 60; //3 minutes -Jwts.parserBuilder() +Jwts.parser() .setAllowedClockSkewSeconds(seconds) // <---- @@ -1369,7 +1369,7 @@ during parsing for timestamp comparisons can be obtained via a custom time sourc ```java Clock clock = new MyClock(); -Jwts.parserBuilder().setClock(myClock) //... etc ... +Jwts.parser().setClock(myClock) //... etc ... ``` The `JwtParser`'s default `Clock` implementation simply returns `new Date()` to reflect the time when parsing occurs, @@ -1692,7 +1692,7 @@ Please see the main [Compression](#compression) section to see how to compress a You read (parse) a JWS as follows: -1. Use the `Jwts.parserBuilder()` method to create a `JwtParserBuilder` instance. +1. Use the `Jwts.parser()` method to create a `JwtParserBuilder` instance. 2. Call either [setKeyLocator](#key-locator) or `verifyWith` methods to determine the key used to verify the JWS signature. 3. Call the `build()` method on the `JwtParserBuilder` to return a thread-safe `JwtParser`. 4. Finally, call the `parseClaimsJws(String)` method with your jws `String`, producing the original JWS. @@ -1705,7 +1705,7 @@ For example: Jws jws; try { - jws = Jwts.parserBuilder() // (1) + jws = Jwts.parser() // (1) .setKeyLocator(keyLocator) // (2) dynamically lookup verification keys based on each JWS //.verifyWith(key) // or a static key used to verify all encountered JWSs @@ -1740,7 +1740,7 @@ So which key do we use for verification? For example: ```java - Jwts.parserBuilder() + Jwts.parser() .verifyWith(secretKey) // <---- @@ -1751,7 +1751,7 @@ For example: specified on the `JwtParserBuilder`. For example: ```java - Jwts.parserBuilder() + Jwts.parser() .verifyWith(publicKey) // <---- publicKey, not privateKey @@ -2166,7 +2166,7 @@ its size. Please see the main [Compression](#compression) section to see how to You read (parse) a JWE as follows: -1. Use the `Jwts.parserBuilder()` method to create a `JwtParserBuilder` instance. +1. Use the `Jwts.parser()` method to create a `JwtParserBuilder` instance. 2. Call either [setKeyLocator](#key-locator) or `decryptWith` methods to determine the key used to decrypt the JWE. 4. Call the `JwtParserBuilder`'s `build()` method to create a thread-safe `JwtParser`. 5. Parse the jwe string with the `JwtParser`'s `parseClaimsJwe` or `parseContentJwe` method. @@ -2178,7 +2178,7 @@ For example: Jwe jwe; try { - jwe = Jwts.parserBuilder() // (1) + jwe = Jwts.parser() // (1) .setKeyLocator(keyLocator) // (2) dynamically lookup decryption keys based on each JWE //.decryptWith(key) // or a static key used to decrypt all encountered JWEs @@ -2212,7 +2212,7 @@ So which key do we use for decryption? `JwtParserBuilder`. For example: ```java - Jwts.parserBuilder() + Jwts.parser() .decryptWith(secretKey) // <---- @@ -2223,7 +2223,7 @@ So which key do we use for decryption? `Password` must be specified on the `JwtParserBuilder`. For example: ```java - Jwts.parserBuilder() + Jwts.parser() .decryptWith(password) // <---- an `io.jsonwebtoken.security.Password` instance @@ -2234,7 +2234,7 @@ So which key do we use for decryption? the `PublicKey`) must be specified on the `JwtParserBuilder`. For example: ```java - Jwts.parserBuilder() + Jwts.parser() .decryptWith(privateKey) // <---- a `PrivateKey`, not a `PublicKey` @@ -2583,7 +2583,7 @@ by calling the `JwtParserBuilder`'s `addCompressionCodecs` method. For example: ```java CompressionCodec myCodec = new MyCompressionCodec(); -Jwts.parserBuilder() +Jwts.parser() .addCompressionCodecs(Collections.of(myCodec)) // <---- @@ -2629,7 +2629,7 @@ You then provide your custom `Locator` to the `JwtParserBuilde ```java Locator myCodecLocator = new MyCompressionCodecLocator(); -Jwts.parserBuilder() +Jwts.parser() .setCompressionCodecLocator(myCodecLocator) // <---- @@ -2694,7 +2694,7 @@ When reading a JWT: ```java Deserializer> deserializer = getMyDeserializer(); //implement me -Jwts.parserBuilder() +Jwts.parser() .deserializeJsonWith(deserializer) @@ -2754,7 +2754,7 @@ and the `JacksonDeserializer` using your `ObjectMapper` on the `JwtParserBuilder ```java ObjectMapper objectMapper = getMyObjectMapper(); //implement me -Jwts.parserBuilder() +Jwts.parser() .deserializeJsonWith(new JacksonDeserializer(objectMapper)) @@ -2786,7 +2786,7 @@ payload of: The `User` object could be retrieved from the `user` claim with the following code: ```java -Jwts.parserBuilder() +Jwts.parser() .deserializeJsonWith(new JacksonDeserializer(Maps.of("user", User.class).build())) // <----- @@ -3027,7 +3027,7 @@ and the `JwtParserBuilder`'s `base64UrlDecodeWith` method to set the decoder: ```java Decoder base64UrlDecoder = getMyBase64UrlDecoder(); //implement me -Jwts.parserBuilder() +Jwts.parser() .base64UrlDecodeWith(base64UrlEncoder) @@ -3078,7 +3078,7 @@ byte[] content = message.getBytes(StandardCharsets.UTF_8); String jws = Jwts.builder().setContent(content, "text/plain").signWith(key, alg).compact(); // Parse the compact JWS: -content = Jwts.parserBuilder().verifyWith(key).build().parseContentJws(jws).getPayload(); +content = Jwts.parser().verifyWith(key).build().parseContentJws(jws).getPayload(); assert message.equals(new String(content, StandardCharsets.UTF_8)); ``` @@ -3104,7 +3104,7 @@ String jws = Jwts.builder().setSubject("Alice") .compact(); // Alice receives and verifies the compact JWS came from Bob: -String subject = Jwts.parserBuilder() +String subject = Jwts.parser() .verifyWith(pair.getPublic()) // <-- Bob's RSA public key .build().parseClaimsJws(jws).getPayload().getSubject(); @@ -3135,7 +3135,7 @@ String jws = Jwts.builder().setSubject("Alice") .compact(); // Alice receives and verifies the compact JWS came from Bob: -String subject = Jwts.parserBuilder() +String subject = Jwts.parser() .verifyWith(pair.getPublic()) // <-- Bob's EC public key .build().parseClaimsJws(jws).getPayload().getSubject(); @@ -3179,7 +3179,7 @@ String jws = Jwts.builder().setSubject("Alice") .compact(); // Alice receives and verifies the compact JWS came from Bob: -String subject = Jwts.parserBuilder() +String subject = Jwts.parser() .verifyWith(pair.getPublic()) // <-- Bob's Edwards Curve public key .build().parseClaimsJws(jws).getPayload().getSubject(); @@ -3220,7 +3220,7 @@ byte[] content = message.getBytes(StandardCharsets.UTF_8); String jwe = Jwts.builder().setContent(content, "text/plain").encryptWith(key, enc).compact(); // Parse the compact JWE: -content = Jwts.parserBuilder().decryptWith(key).build().parseContentJwe(jwe).getPayload(); +content = Jwts.parser().decryptWith(key).build().parseContentJwe(jwe).getPayload(); assert message.equals(new String(content, StandardCharsets.UTF_8)); ``` @@ -3252,7 +3252,7 @@ String jwe = Jwts.builder().setAudience("Alice") .compact(); // Alice receives and decrypts the compact JWE: -String audience = Jwts.parserBuilder() +String audience = Jwts.parser() .decryptWith(pair.getPrivate()) // <-- Alice's RSA private key .build().parseClaimsJwe(jwe).getPayload().getAudience(); @@ -3285,7 +3285,7 @@ AeadAlgorithm enc = Jwts.ENC.A256GCM; //or A192GCM, A128GCM, A256CBC-HS512, etc. String jwe = Jwts.builder().setIssuer("me").encryptWith(key, alg, enc).compact(); // Parse the compact JWE: -String issuer = Jwts.parserBuilder().decryptWith(key).build() +String issuer = Jwts.parser().decryptWith(key).build() .parseClaimsJwe(jwe).getPayload().getIssuer(); assert "me".equals(issuer); @@ -3320,7 +3320,7 @@ String jwe = Jwts.builder().setAudience("Alice") .compact(); // Alice receives and decrypts the compact JWE: -String audience = Jwts.parserBuilder() +String audience = Jwts.parser() .decryptWith(pair.getPrivate()) // <-- Alice's EC private key .build().parseClaimsJwe(jwe).getPayload().getAudience(); @@ -3367,7 +3367,7 @@ String jwe = Jwts.builder().setIssuer("me") .compact(); // Parse the compact JWE: -String issuer = Jwts.parserBuilder().decryptWith(password) +String issuer = Jwts.parser().decryptWith(password) .build().parseClaimsJwe(jwe).getPayload().getIssuer(); assert "me".equals(issuer); diff --git a/api/src/main/java/io/jsonwebtoken/CompressionCodecResolver.java b/api/src/main/java/io/jsonwebtoken/CompressionCodecResolver.java index ce9fb5160..07d6f1983 100644 --- a/api/src/main/java/io/jsonwebtoken/CompressionCodecResolver.java +++ b/api/src/main/java/io/jsonwebtoken/CompressionCodecResolver.java @@ -28,7 +28,7 @@ *

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

+ * {@link io.jsonwebtoken.JwtParserBuilder#setCompressionCodecResolver(CompressionCodecResolver) parsing} JWTs.

* * @see JwtParserBuilder#setCompressionCodecResolver(CompressionCodecResolver) * @see JwtParserBuilder#addCompressionAlgorithms(Collection) diff --git a/api/src/main/java/io/jsonwebtoken/Identifiable.java b/api/src/main/java/io/jsonwebtoken/Identifiable.java index e02b9a1f3..9d2cc8d92 100644 --- a/api/src/main/java/io/jsonwebtoken/Identifiable.java +++ b/api/src/main/java/io/jsonwebtoken/Identifiable.java @@ -40,7 +40,7 @@ * parameter value. * * - * {@link io.jsonwebtoken.CompressionCodec CompressionCodec} + * {@link io.jsonwebtoken.io.CompressionAlgorithm CompressionAlgorithm} * JWE protected header's * {@code zip} (Compression Algorithm) * parameter value. diff --git a/api/src/main/java/io/jsonwebtoken/JwtParser.java b/api/src/main/java/io/jsonwebtoken/JwtParser.java index 5499701ae..3efc658ba 100644 --- a/api/src/main/java/io/jsonwebtoken/JwtParser.java +++ b/api/src/main/java/io/jsonwebtoken/JwtParser.java @@ -15,392 +15,16 @@ */ package io.jsonwebtoken; -import io.jsonwebtoken.io.Decoder; -import io.jsonwebtoken.io.Deserializer; import io.jsonwebtoken.security.SecurityException; import io.jsonwebtoken.security.SignatureException; -import java.security.Key; -import java.util.Collection; -import java.util.Date; -import java.util.Map; - /** * A parser for reading JWT strings, used to convert them into a {@link Jwt} object representing the expanded JWT. * * @since 0.1 */ -@SuppressWarnings("DeprecatedIsStillUsed") public interface JwtParser { - /** - * Deprecated - this was an implementation detail accidentally added to the public interface. This - * will be removed in a future release. - * - * @deprecated since JJWT_RELEASE_VERSION, to be removed in a future relase. - */ - @Deprecated - char SEPARATOR_CHAR = '.'; - - /** - * Ensures that the specified {@code jti} exists in the parsed JWT. If missing or if the parsed - * value does not equal the specified value, an exception will be thrown indicating that the - * JWT is invalid and may not be used. - * - * @param id the {@code jti} value that must exist in the parsed JWT. - * @return the parser method for chaining. - * @see MissingClaimException - * @see IncorrectClaimException - * @deprecated see {@link JwtParserBuilder#requireId(String)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser requireId(String id); - - /** - * Ensures that the specified {@code sub} exists in the parsed JWT. If missing or if the parsed - * value does not equal the specified value, an exception will be thrown indicating that the - * JWT is invalid and may not be used. - * - * @param subject the {@code sub} value that must exist in the parsed JWT. - * @return the parser for method chaining. - * @see MissingClaimException - * @see IncorrectClaimException - * @deprecated see {@link JwtParserBuilder#requireSubject(String)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser requireSubject(String subject); - - /** - * Ensures that the specified {@code aud} exists in the parsed JWT. If missing or if the parsed - * value does not equal the specified value, an exception will be thrown indicating that the - * JWT is invalid and may not be used. - * - * @param audience the {@code aud} value that must exist in the parsed JWT. - * @return the parser for method chaining. - * @see MissingClaimException - * @see IncorrectClaimException - * @deprecated see {@link JwtParserBuilder#requireAudience(String)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser requireAudience(String audience); - - /** - * Ensures that the specified {@code iss} exists in the parsed JWT. If missing or if the parsed - * value does not equal the specified value, an exception will be thrown indicating that the - * JWT is invalid and may not be used. - * - * @param issuer the {@code iss} value that must exist in the parsed JWT. - * @return the parser for method chaining. - * @see MissingClaimException - * @see IncorrectClaimException - * @deprecated see {@link JwtParserBuilder#requireIssuer(String)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser requireIssuer(String issuer); - - /** - * Ensures that the specified {@code iat} exists in the parsed JWT. If missing or if the parsed - * value does not equal the specified value, an exception will be thrown indicating that the - * JWT is invalid and may not be used. - * - * @param issuedAt the {@code iat} value that must exist in the parsed JWT. - * @return the parser for method chaining. - * @see MissingClaimException - * @see IncorrectClaimException - * @deprecated see {@link JwtParserBuilder#requireIssuedAt(Date)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser requireIssuedAt(Date issuedAt); - - /** - * Ensures that the specified {@code exp} exists in the parsed JWT. If missing or if the parsed - * value does not equal the specified value, an exception will be thrown indicating that the - * JWT is invalid and may not be used. - * - * @param expiration the {@code exp} value that must exist in the parsed JWT. - * @return the parser for method chaining. - * @see MissingClaimException - * @see IncorrectClaimException - * @deprecated see {@link JwtParserBuilder#requireExpiration(Date)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser requireExpiration(Date expiration); - - /** - * Ensures that the specified {@code nbf} exists in the parsed JWT. If missing or if the parsed - * value does not equal the specified value, an exception will be thrown indicating that the - * JWT is invalid and may not be used. - * - * @param notBefore the {@code nbf} value that must exist in the parsed JWT. - * @return the parser for method chaining - * @see MissingClaimException - * @see IncorrectClaimException - * @deprecated see {@link JwtParserBuilder#requireNotBefore(Date)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser requireNotBefore(Date notBefore); - - /** - * Ensures that the specified {@code claimName} exists in the parsed JWT. If missing or if the parsed - * value does not equal the specified value, an exception will be thrown indicating that the - * JWT is invalid and may not be used. - * - * @param claimName the name of a claim that must exist in the parsed JWT. - * @param value the value that must exist for the specified {@code claimName} in the JWT. - * @return the parser for method chaining. - * @see MissingClaimException - * @see IncorrectClaimException - * @deprecated see {@link JwtParserBuilder#require(String, Object)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser require(String claimName, Object value); - - /** - * Sets the {@link Clock} that determines the timestamp to use when validating the parsed JWT. - * The parser uses a default Clock implementation that simply returns {@code new Date()} when called. - * - * @param clock a {@code Clock} object to return the timestamp to use when validating the parsed JWT. - * @return the parser for method chaining. - * @since 0.7.0 - * @deprecated see {@link JwtParserBuilder#setClock(Clock)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser setClock(Clock clock); - - /** - * Sets the amount of clock skew in seconds to tolerate when verifying the local time against the {@code exp} - * and {@code nbf} claims. - * - * @param seconds the number of seconds to tolerate for clock skew when verifying {@code exp} or {@code nbf} claims. - * @return the parser for method chaining. - * @throws IllegalArgumentException if {@code seconds} is a value greater than {@code Long.MAX_VALUE / 1000} as - * any such value would cause numeric overflow when multiplying by 1000 to obtain a millisecond value. - * @since 0.7.0 - * @deprecated see {@link JwtParserBuilder#setAllowedClockSkewSeconds(long)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser setAllowedClockSkewSeconds(long seconds) throws IllegalArgumentException; - - /** - * 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 - * signature. - * @return the parser for method chaining. - * @deprecated in favor of {@link JwtParserBuilder#verifyWith(Key)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser setSigningKey(byte[] key); - - /** - * 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[])}.

- * - *

Deprecation Notice: Deprecated as of 0.10.0, will be removed in 1.0.0

- * - *

This method has been deprecated because the {@code key} argument for this method can be confusing: keys for - * cryptographic operations are always binary (byte arrays), and many people were confused as to how bytes were - * obtained from the String argument.

- * - *

This method always expected a String argument that was effectively the same as the result of the following - * (pseudocode):

- * - *

{@code String base64EncodedSecretKey = base64Encode(secretKeyBytes);}

- * - *

However, a non-trivial number of JJWT users were confused by the method signature and attempted to - * use raw password strings as the key argument - for example {@code setSigningKey(myPassword)} - which is - * almost always incorrect for cryptographic hashes and can produce erroneous or insecure results.

- * - *

See this - * - * StackOverflow answer explaining why raw (non-base64-encoded) strings are almost always incorrect for - * signature operations.

- * - *

Finally, please use the {@link #setSigningKey(Key) setSigningKey(Key)} instead, as this method and the - * {@code byte[]} variant will be removed before the 1.0.0 release.

- * - * @param base64EncodedSecretKey the BASE64-encoded algorithm-specific signature verification key to use to validate - * any discovered JWS digital signature. - * @return the parser for method chaining. - * @deprecated in favor of {@link JwtParserBuilder#verifyWith(Key)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser setSigningKey(String base64EncodedSecretKey); - - /** - * 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 to use to validate any discovered JWS digital - * signature. - * @return the parser for method chaining. - * @deprecated in favor of {@link JwtParserBuilder#verifyWith(Key)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser setSigningKey(Key key); - - /** - * 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 (content byte array 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
-     *         public byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) {
-     *             //inspect the header or claims, lookup and return the signing key
-     *             return getSigningKey(header, claims); //implement me
-     *         }})
-     *     .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.

- * - * @param signingKeyResolver the signing key resolver used to retrieve the signing key. - * @return the parser for method chaining. - * @since 0.4 - * @deprecated in favor of {@link JwtParserBuilder#setKeyLocator(Locator)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - // TODO: remove for 1.0 - JwtParser setSigningKeyResolver(SigningKeyResolver signingKeyResolver); - - /** - * Sets the {@link CompressionCodecResolver} used to acquire the {@link CompressionCodec} that should be used to - * decompress the JWT payload. If the parsed JWT is not compressed, this resolver is not used. - * - *

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

- * - *

Default Support

- * - *

JJWT's default {@link JwtParser} implementation supports both the {@link Jwts.ZIP#DEF DEFLATE} - * and {@link Jwts.ZIP#GZIP 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 may implement - * your own {@link CompressionCodecResolver} and specify that via this method and also when - * {@link io.jsonwebtoken.JwtBuilder#compressWith(io.jsonwebtoken.io.CompressionAlgorithm) building} JWTs.

- * - * @param compressionCodecResolver the compression codec resolver used to decompress the JWT payload. - * @return the parser for method chaining. - * @since 0.6.0 - * @deprecated since JJWT_RELEASE_VERSION in favor of {@link JwtParserBuilder#addCompressionAlgorithms(Collection)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser setCompressionCodecResolver(CompressionCodecResolver compressionCodecResolver); - - /** - * Perform Base64Url decoding with the specified Decoder - * - *

JJWT uses a spec-compliant decoder that works on all supported JDK versions, but you may call this method - * to specify a different decoder if you desire.

- * - * @param base64UrlDecoder the decoder to use when Base64Url-decoding - * @return the parser for method chaining. - * @since 0.10.0 - * @deprecated see {@link JwtParserBuilder#base64UrlDecodeWith(Decoder)}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser base64UrlDecodeWith(Decoder base64UrlDecoder); - - /** - * Uses the specified deserializer to convert JSON Strings (UTF-8 byte arrays) into Java Map objects. This is - * used by the parser after Base64Url-decoding to convert JWT/JWS/JWT JSON headers and claims into Java Map - * objects. - * - *

If this method is not called, JJWT will use whatever deserializer it can find at runtime, checking for the - * presence of well-known implementations such Jackson, Gson, and org.json. If one of these is not found - * in the runtime classpath, an exception will be thrown when one of the various {@code parse}* methods is - * invoked.

- * - * @param deserializer the deserializer to use when converting JSON Strings (UTF-8 byte arrays) into Map objects. - * @return the parser for method chaining. - * @since 0.10.0 - * @deprecated see {@link JwtParserBuilder#deserializeJsonWith(Deserializer)} )}. - * To construct a JwtParser use the corresponding builder via {@link Jwts#parserBuilder()}. This will construct an - * immutable JwtParser. - *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - JwtParser deserializeJsonWith(Deserializer> deserializer); - /** * Returns {@code true} if the specified JWT compact string represents a signed JWT (aka a 'JWS'), {@code false} * otherwise. @@ -455,7 +79,7 @@ public interface JwtParser { *

      * String compactJwt = request.getParameter("jwt"); //we are confident this is a signed JWS
      *
-     * String subject = Jwts.parser().setSigningKey(key).parse(compactJwt, new JwtHandlerAdapter<String>() {
+     * String subject = Jwts.parser().verifyWith(key).build().parse(compactJwt, new JwtHandlerAdapter<String>() {
      *     @Override
      *     public String onClaimsJws(Jws<Claims> jws) {
      *         return jws.getBody().getSubject();
diff --git a/api/src/main/java/io/jsonwebtoken/JwtParserBuilder.java b/api/src/main/java/io/jsonwebtoken/JwtParserBuilder.java
index b2b8de3b6..eadf800ea 100644
--- a/api/src/main/java/io/jsonwebtoken/JwtParserBuilder.java
+++ b/api/src/main/java/io/jsonwebtoken/JwtParserBuilder.java
@@ -32,7 +32,7 @@
 /**
  * A builder to construct a {@link JwtParser}. Example usage:
  * 
{@code
- *     Jwts.parserBuilder()
+ *     Jwts.parser()
  *         .requireIssuer("https://issuer.example.com")
  *         .verifyWith(...)
  *         .build()
@@ -331,8 +331,9 @@ public interface JwtParserBuilder extends Builder {
     JwtParserBuilder verifyWith(Key key);
 
     /**
-     * Sets the decryption key to be used to decrypt all encountered JWEs.  If the encountered JWT string is not a
-     * JWE (e.g. a JWS), this key is not used.
+     * Sets the decryption key used to decrypt all encountered JWEs, overwriting any previously configured
+     * {@link #setKeyLocator(Locator) keyLocator}. If the encountered JWT string is not a JWE (e.g. a JWS),
+     * this key is not used.
      *
      * 

This is a convenience method to use in specific circumstances: when the parser will only ever encounter * JWEs that can always be decrypted by a single key. This also implies that this key MUST be a valid @@ -342,7 +343,7 @@ public interface JwtParserBuilder extends Builder { *

If there is any chance that the parser will encounter JWEs that need different decryption keys based on the * JWE being parsed, or JWSs, it is strongly recommended to configure * your own {@link Locator Locator} via the {@link #setKeyLocator(Locator) setKeyLocator} method instead of - * using this one.

+ * using {@code decryptWith}.

* *

Calling this method overrides any previously set decryption key.

* @@ -366,7 +367,7 @@ public interface JwtParserBuilder extends Builder { * verify the JWS signature or decrypt the JWE payload with the returned key. For example:

* *
-     * Jws<Claims> jws = Jwts.parserBuilder().setKeyLocator(new Locator<Key>() {
+     * Jws<Claims> jws = Jwts.parser().setKeyLocator(new Locator<Key>() {
      *         @Override
      *         public Key locate(Header<?> header) {
      *             if (header instanceof JwsHeader) {
@@ -412,7 +413,7 @@ public interface JwtParserBuilder extends Builder {
      *             //inspect the header or claims, lookup and return the signing key
      *             return getSigningKey(header, claims); //implement me
      *         }})
-     *     .parseClaimsJws(compact);
+     *     .build().parseClaimsJws(compact);
      * 
* *

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

diff --git a/api/src/main/java/io/jsonwebtoken/Jwts.java b/api/src/main/java/io/jsonwebtoken/Jwts.java index 5d4c3e244..8c1ca43ac 100644 --- a/api/src/main/java/io/jsonwebtoken/Jwts.java +++ b/api/src/main/java/io/jsonwebtoken/Jwts.java @@ -1056,38 +1056,12 @@ public static Claims claims(Map claims) { return claims().set(claims).build(); } - /** - * Returns a new {@link JwtParser} instance that can be configured and then used to parse JWT strings. - * - * @return a new {@link JwtParser} instance that can be configured and then used to parse JWT strings. - * @deprecated use {@link Jwts#parserBuilder()} instead. See {@link JwtParserBuilder} for usage details. - *

Migration to new method structure is minimal, for example: - *

Old code: - *

{@code
-     *     Jwts.parser()
-     *         .requireAudience("string")
-     *         .parse(jwtString)
-     * }
- *

New code: - *

{@code
-     *     Jwts.parserBuilder()
-     *         .requireAudience("string")
-     *         .build()
-     *         .parse(jwtString)
-     * }
- *

NOTE: this method will be removed before version 1.0 - */ - @Deprecated - public static JwtParser parser() { - return Classes.newInstance("io.jsonwebtoken.impl.DefaultJwtParser"); - } - /** * Returns a new {@link JwtParserBuilder} instance that can be configured to create an immutable/thread-safe {@link JwtParser}. * * @return a new {@link JwtParser} instance that can be configured create an immutable/thread-safe {@link JwtParser}. */ - public static JwtParserBuilder parserBuilder() { + public static JwtParserBuilder parser() { return Classes.newInstance("io.jsonwebtoken.impl.DefaultJwtParserBuilder"); } diff --git a/api/src/main/java/io/jsonwebtoken/SigningKeyResolver.java b/api/src/main/java/io/jsonwebtoken/SigningKeyResolver.java index 33f642be1..eb78e008d 100644 --- a/api/src/main/java/io/jsonwebtoken/SigningKeyResolver.java +++ b/api/src/main/java/io/jsonwebtoken/SigningKeyResolver.java @@ -33,7 +33,7 @@ * //inspect the header or claims, lookup and return the signing key * return getSigningKeyBytes(header, claims); //implement me * }}) - * .parseClaimsJws(compact); + * .build().parseClaimsJws(compact); *

* *

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

diff --git a/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java b/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java index 1a256cdfd..50c6ea6b9 100644 --- a/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java +++ b/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java @@ -40,21 +40,17 @@ import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.impl.lang.Bytes; import io.jsonwebtoken.impl.lang.Function; -import io.jsonwebtoken.impl.lang.LegacyServices; -import io.jsonwebtoken.impl.security.ConstantKeyLocator; import io.jsonwebtoken.impl.security.DefaultAeadResult; import io.jsonwebtoken.impl.security.DefaultDecryptionKeyRequest; import io.jsonwebtoken.impl.security.DefaultVerifySecureDigestRequest; import io.jsonwebtoken.impl.security.LocatingKeyResolver; import io.jsonwebtoken.io.CompressionAlgorithm; import io.jsonwebtoken.io.Decoder; -import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.io.DecodingException; import io.jsonwebtoken.io.DeserializationException; import io.jsonwebtoken.io.Deserializer; import io.jsonwebtoken.lang.Arrays; import io.jsonwebtoken.lang.Assert; -import io.jsonwebtoken.lang.Collections; import io.jsonwebtoken.lang.DateFormats; import io.jsonwebtoken.lang.Strings; import io.jsonwebtoken.security.AeadAlgorithm; @@ -62,7 +58,6 @@ import io.jsonwebtoken.security.DecryptionKeyRequest; import io.jsonwebtoken.security.InvalidKeyException; import io.jsonwebtoken.security.KeyAlgorithm; -import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.Message; import io.jsonwebtoken.security.SecureDigestAlgorithm; import io.jsonwebtoken.security.SignatureException; @@ -82,8 +77,6 @@ public class DefaultJwtParser implements JwtParser { static final char SEPARATOR_CHAR = '.'; - private static final int MILLISECONDS_PER_SECOND = 1000; - private static final JwtTokenizer jwtTokenizer = new JwtTokenizer(); public static final String INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE = "Expected %s claim to be: %s, but was: %s."; @@ -131,68 +124,34 @@ public class DefaultJwtParser implements JwtParser { "enableUnsecuredDecompression() method (but please read the security considerations covered in that " + "method's JavaDoc before doing so)."; - private static Function> sigFn(Collection> extras) { - return new IdLocator<>(DefaultHeader.ALGORITHM, Jwts.SIG.get(), extras, MISSING_JWS_ALG_MSG); - } - - private static Function encFn(Collection extras) { - return new IdLocator<>(DefaultJweHeader.ENCRYPTION_ALGORITHM, Jwts.ENC.get(), extras, MISSING_ENC_MSG); - } - - private static Function> keyFn(Collection> extras) { - return new IdLocator<>(DefaultHeader.ALGORITHM, Jwts.KEY.get(), extras, MISSING_JWE_ALG_MSG); - } - - private static IdLocator zipFn(Collection extras) { - return new IdLocator<>(DefaultHeader.COMPRESSION_ALGORITHM, Jwts.ZIP.get(), extras, null); - } - - // TODO: make the following fields final for v1.0 - private Provider provider; + private final Provider provider; - @SuppressWarnings("deprecation") // will remove for 1.0 - private SigningKeyResolver signingKeyResolver; + @SuppressWarnings("deprecation") + private final SigningKeyResolver signingKeyResolver; private final boolean enableUnsecuredJws; private final boolean enableUnsecuredDecompression; - private final Function> signatureAlgorithmLocator; + private final Function> sigAlgFn; - private final Function encryptionAlgorithmLocator; + private final Function encAlgFn; - private final Function> keyAlgorithmLocator; + private final Function> keyAlgFn; - private Function compressionAlgorithmLocator; + private final Function zipAlgFn; private final Locator keyLocator; - private Decoder base64UrlDecoder = Decoders.BASE64URL; + private final Decoder base64UrlDecoder; - private Deserializer> deserializer; + private final Deserializer> deserializer; - private ClaimsBuilder expectedClaims = Jwts.claims(); + private final ClaimsBuilder expectedClaims; - private Clock clock = DefaultClock.INSTANCE; + private final Clock clock; - private long allowedClockSkewMillis = 0; - - /** - * TODO: remove this constructor before 1.0 - * - * @deprecated for backward compatibility only, see other constructors. - */ - @SuppressWarnings("DeprecatedIsStillUsed") // will remove before 1.0 - @Deprecated - public DefaultJwtParser() { - this.keyLocator = new ConstantKeyLocator(null, null); - this.signatureAlgorithmLocator = sigFn(Collections.>emptyList()); - this.keyAlgorithmLocator = keyFn(Collections.>emptyList()); - this.encryptionAlgorithmLocator = encFn(Collections.emptyList()); - this.compressionAlgorithmLocator = zipFn(Collections.emptyList()); - this.enableUnsecuredJws = false; - this.enableUnsecuredDecompression = false; - } + private final long allowedClockSkewMillis; //SigningKeyResolver will be removed for 1.0: @SuppressWarnings("deprecation") @@ -216,134 +175,17 @@ public DefaultJwtParser() { this.enableUnsecuredDecompression = enableUnsecuredDecompression; this.signingKeyResolver = signingKeyResolver; this.keyLocator = Assert.notNull(keyLocator, "Key Locator cannot be null."); - this.clock = clock; + this.clock = Assert.notNull(clock, "Clock cannot be null."); this.allowedClockSkewMillis = allowedClockSkewMillis; this.expectedClaims = Jwts.claims().set(expectedClaims); - this.base64UrlDecoder = base64UrlDecoder; - this.deserializer = deserializer; - this.signatureAlgorithmLocator = sigFn(extraSigAlgs); - this.keyAlgorithmLocator = keyFn(extraKeyAlgs); - this.encryptionAlgorithmLocator = encFn(extraEncAlgs); - - if (compressionCodecResolver != null) { - this.compressionAlgorithmLocator = new CompressionCodecLocator(compressionCodecResolver); - } else { - this.compressionAlgorithmLocator = zipFn(extraZipAlgs); - } - } + this.base64UrlDecoder = Assert.notNull(base64UrlDecoder, "base64UrlDecoder cannot be null."); + this.deserializer = Assert.notNull(deserializer, "Deserializer cannot be null."); - @Override - public JwtParser deserializeJsonWith(Deserializer> deserializer) { - Assert.notNull(deserializer, "deserializer cannot be null."); - this.deserializer = new JwtDeserializer<>(deserializer); - return this; - } - - @Override - public JwtParser base64UrlDecodeWith(Decoder base64UrlDecoder) { - Assert.notNull(base64UrlDecoder, "base64UrlDecoder cannot be null."); - this.base64UrlDecoder = base64UrlDecoder; - return this; - } - - @Override - public JwtParser requireIssuedAt(Date issuedAt) { - expectedClaims.setIssuedAt(issuedAt); - return this; - } - - @Override - public JwtParser requireIssuer(String issuer) { - expectedClaims.setIssuer(issuer); - return this; - } - - @Override - public JwtParser requireAudience(String audience) { - expectedClaims.setAudience(audience); - return this; - } - - @Override - public JwtParser requireSubject(String subject) { - expectedClaims.setSubject(subject); - return this; - } - - @Override - public JwtParser requireId(String id) { - expectedClaims.setId(id); - return this; - } - - @Override - public JwtParser requireExpiration(Date expiration) { - expectedClaims.setExpiration(expiration); - return this; - } - - @Override - public JwtParser requireNotBefore(Date notBefore) { - expectedClaims.setNotBefore(notBefore); - return this; - } - - @Override - public JwtParser require(String claimName, Object value) { - Assert.hasText(claimName, "claim name cannot be null or empty."); - Assert.notNull(value, "The value cannot be null for claim name: " + claimName); - expectedClaims.set(claimName, value); - return this; - } - - @Override - public JwtParser setClock(Clock clock) { - Assert.notNull(clock, "Clock instance cannot be null."); - this.clock = clock; - return this; - } - - @Override - public JwtParser setAllowedClockSkewSeconds(long seconds) throws IllegalArgumentException { - Assert.isTrue(seconds <= DefaultJwtParserBuilder.MAX_CLOCK_SKEW_MILLIS, DefaultJwtParserBuilder.MAX_CLOCK_SKEW_ILLEGAL_MSG); - this.allowedClockSkewMillis = Math.max(0, seconds * MILLISECONDS_PER_SECOND); - return this; - } - - @Override - public JwtParser setSigningKey(byte[] key) { - Assert.notEmpty(key, "signing key cannot be null or empty."); - return setSigningKey(Keys.hmacShaKeyFor(key)); - } - - @Override - public JwtParser setSigningKey(String base64EncodedSecretKey) { - Assert.hasText(base64EncodedSecretKey, "signing key cannot be null or empty."); - byte[] bytes = Decoders.BASE64.decode(base64EncodedSecretKey); - return setSigningKey(bytes); - } - - @Override - public JwtParser setSigningKey(final Key key) { - Assert.notNull(key, "signing key cannot be null."); - setSigningKeyResolver(new ConstantKeyLocator(key, null)); - return this; - } - - @SuppressWarnings("deprecation") // required until 1.0 - @Override - public JwtParser setSigningKeyResolver(SigningKeyResolver signingKeyResolver) { - Assert.notNull(signingKeyResolver, "SigningKeyResolver cannot be null."); - this.signingKeyResolver = signingKeyResolver; - return this; - } - - @SuppressWarnings("deprecation") - @Override - public JwtParser setCompressionCodecResolver(CompressionCodecResolver resolver) { - Assert.notNull(resolver, "CompressionCodecResolver cannot be null."); - this.compressionAlgorithmLocator = new CompressionCodecLocator(resolver); - return this; + this.sigAlgFn = new IdLocator<>(DefaultHeader.ALGORITHM, Jwts.SIG.get(), extraSigAlgs, MISSING_JWS_ALG_MSG); + this.keyAlgFn = new IdLocator<>(DefaultHeader.ALGORITHM, Jwts.KEY.get(), extraKeyAlgs, MISSING_JWE_ALG_MSG); + this.encAlgFn = new IdLocator<>(DefaultJweHeader.ENCRYPTION_ALGORITHM, Jwts.ENC.get(), extraEncAlgs, MISSING_ENC_MSG); + this.zipAlgFn = compressionCodecResolver != null ? new CompressionCodecLocator(compressionCodecResolver) : + new IdLocator<>(DefaultHeader.COMPRESSION_ALGORITHM, Jwts.ZIP.get(), extraZipAlgs, null); } @Override @@ -442,7 +284,7 @@ private void verifySignature(final TokenizedJwt tokenized, final JwsHeader jwsHe SecureDigestAlgorithm algorithm; try { - algorithm = (SecureDigestAlgorithm) signatureAlgorithmLocator.apply(jwsHeader); + algorithm = (SecureDigestAlgorithm) sigAlgFn.apply(jwsHeader); } catch (UnsupportedJwtException e) { //For backwards compatibility. TODO: remove this try/catch block for 1.0 and let UnsupportedJwtException propagate String msg = "Unsupported signature algorithm '" + alg + "'"; @@ -494,15 +336,6 @@ private void verifySignature(final TokenizedJwt tokenized, final JwsHeader jwsHe @Override public Jwt parse(String compact) throws ExpiredJwtException, MalformedJwtException, SignatureException { - // TODO, this logic is only need for a now deprecated code path - // remove this block in v1.0 (the equivalent is already in DefaultJwtParserBuilder) - if (this.deserializer == null) { - // try to find one based on the services available - // TODO: This util class will throw a UnavailableImplementationException here to retain behavior of previous version, remove in v1.0 - //noinspection deprecation - this.deserializer = LegacyServices.loadFirst(Deserializer.class); - } - Assert.hasText(compact, "JWT String cannot be null or empty."); final TokenizedJwt tokenized = jwtTokenizer.tokenize(compact); @@ -607,10 +440,10 @@ private void verifySignature(final TokenizedJwt tokenized, final JwsHeader jwsHe if (!Strings.hasText(enc)) { throw new MalformedJwtException(MISSING_ENC_MSG); } - final AeadAlgorithm encAlg = this.encryptionAlgorithmLocator.apply(jweHeader); + final AeadAlgorithm encAlg = this.encAlgFn.apply(jweHeader); Assert.stateNotNull(encAlg, "JWE Encryption Algorithm cannot be null."); - @SuppressWarnings("rawtypes") final KeyAlgorithm keyAlg = this.keyAlgorithmLocator.apply(jweHeader); + @SuppressWarnings("rawtypes") final KeyAlgorithm keyAlg = this.keyAlgFn.apply(jweHeader); Assert.stateNotNull(keyAlg, "JWE Key Algorithm cannot be null."); final Key key = this.keyLocator.locate(jweHeader); @@ -639,7 +472,7 @@ private void verifySignature(final TokenizedJwt tokenized, final JwsHeader jwsHe verifySignature(tokenized, ((JwsHeader) header), alg, new LocatingKeyResolver(this.keyLocator), null, null); } - CompressionAlgorithm compressionAlgorithm = compressionAlgorithmLocator.apply(header); + CompressionAlgorithm compressionAlgorithm = zipAlgFn.apply(header); if (compressionAlgorithm != null) { if (unsecured && !enableUnsecuredDecompression) { String msg = String.format(UNPROTECTED_DECOMPRESSION_MSG, compressionAlgorithm.getId()); diff --git a/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParserBuilder.java b/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParserBuilder.java index eda46473e..0b797bad3 100644 --- a/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParserBuilder.java +++ b/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParserBuilder.java @@ -282,16 +282,26 @@ public JwtParser build() { } if (this.signingKeyResolver != null && this.signatureVerificationKey != null) { - String msg = "Both 'signingKeyResolver and 'verifyWith/signWith' key cannot be configured. " + + String msg = "Both a 'signingKeyResolver and a 'verifyWith' key cannot be configured. " + "Choose either, or prefer `keyLocator` when possible."; throw new IllegalStateException(msg); } - if (this.keyLocator != null && this.decryptionKey != null) { - String msg = "Both 'keyLocator' and 'decryptWith' key cannot be configured. Prefer 'keyLocator' if possible."; - throw new IllegalStateException(msg); + if (this.keyLocator != null) { + if (this.signatureVerificationKey != null) { + String msg = "Both 'keyLocator' and a 'verifyWith' key cannot be configured. " + + "Prefer 'keyLocator' if possible."; + throw new IllegalStateException(msg); + } + if (this.decryptionKey != null) { + String msg = "Both 'keyLocator' and a 'decryptWith' key cannot be configured. " + + "Prefer 'keyLocator' if possible."; + throw new IllegalStateException(msg); + } } - if (this.keyLocator == null) { - this.keyLocator = new ConstantKeyLocator(this.signatureVerificationKey, this.decryptionKey); + + Locator keyLocator = this.keyLocator; // user configured default, don't overwrite to ensure further build() calls work as expected + if (keyLocator == null) { + keyLocator = new ConstantKeyLocator(this.signatureVerificationKey, this.decryptionKey); } if (!enableUnsecuredJws && enableUnsecuredDecompression) { @@ -306,13 +316,12 @@ public JwtParser build() { throw new IllegalStateException(msg); } - // Invariants. If these are ever violated, it's an error in this class implementation - // (we default to non-null instances, and the setters should never allow null): - Assert.stateNotNull(this.keyLocator, "Key locator should never be null."); + // Invariants. If these are ever violated, it's an error in this class implementation: + Assert.stateNotNull(keyLocator, "Key locator should never be null."); final DefaultClaims expClaims = (DefaultClaims) this.expectedClaims.build(); - return new ImmutableJwtParser(new DefaultJwtParser( + return new DefaultJwtParser( provider, signingKeyResolver, enableUnsecuredJws, @@ -328,6 +337,6 @@ public JwtParser build() { extraSigAlgs, extraKeyAlgs, extraEncAlgs - )); + ); } } diff --git a/impl/src/main/java/io/jsonwebtoken/impl/ImmutableJwtParser.java b/impl/src/main/java/io/jsonwebtoken/impl/ImmutableJwtParser.java deleted file mode 100644 index c48fcbe17..000000000 --- a/impl/src/main/java/io/jsonwebtoken/impl/ImmutableJwtParser.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2019 jsonwebtoken.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.jsonwebtoken.impl; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Clock; -import io.jsonwebtoken.CompressionCodecResolver; -import io.jsonwebtoken.ExpiredJwtException; -import io.jsonwebtoken.Header; -import io.jsonwebtoken.Jwe; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.JwtException; -import io.jsonwebtoken.JwtHandler; -import io.jsonwebtoken.JwtParser; -import io.jsonwebtoken.MalformedJwtException; -import io.jsonwebtoken.SigningKeyResolver; -import io.jsonwebtoken.UnsupportedJwtException; -import io.jsonwebtoken.io.Decoder; -import io.jsonwebtoken.io.Deserializer; -import io.jsonwebtoken.security.SignatureException; - -import java.security.Key; -import java.util.Date; -import java.util.Map; - -/** - * This JwtParser implementation exists as a stop gap until the mutable methods are removed from JwtParser. - * TODO: remove this class BEFORE 1.0 - * - * @since 0.11.0 - */ -class ImmutableJwtParser implements JwtParser { - - private final JwtParser jwtParser; - - ImmutableJwtParser(JwtParser jwtParser) { - this.jwtParser = jwtParser; - } - - private IllegalStateException doNotMutate() { - return new IllegalStateException("Cannot mutate a JwtParser created from JwtParserBuilder.build(), " + - "the mutable methods in JwtParser will be removed before version 1.0"); - } - - @Override - public JwtParser requireId(String id) { - throw doNotMutate(); - } - - @Override - public JwtParser requireSubject(String subject) { - throw doNotMutate(); - } - - @Override - public JwtParser requireAudience(String audience) { - throw doNotMutate(); - } - - @Override - public JwtParser requireIssuer(String issuer) { - throw doNotMutate(); - } - - @Override - public JwtParser requireIssuedAt(Date issuedAt) { - throw doNotMutate(); - } - - @Override - public JwtParser requireExpiration(Date expiration) { - throw doNotMutate(); - } - - @Override - public JwtParser requireNotBefore(Date notBefore) { - throw doNotMutate(); - } - - @Override - public JwtParser require(String claimName, Object value) { - throw doNotMutate(); - } - - @Override - public JwtParser setClock(Clock clock) { - throw doNotMutate(); - } - - @Override - public JwtParser setAllowedClockSkewSeconds(long seconds) { - throw doNotMutate(); - } - - @Override - public JwtParser setSigningKey(byte[] key) { - throw doNotMutate(); - } - - @Override - public JwtParser setSigningKey(String base64EncodedSecretKey) { - throw doNotMutate(); - } - - @Override - public JwtParser setSigningKey(Key key) { - throw doNotMutate(); - } - - @Override - public JwtParser setSigningKeyResolver(SigningKeyResolver signingKeyResolver) { - throw doNotMutate(); - } - - @Override - public JwtParser setCompressionCodecResolver(CompressionCodecResolver compressionCodecResolver) { - throw doNotMutate(); - } - - @Override - public JwtParser base64UrlDecodeWith(Decoder base64UrlDecoder) { - throw doNotMutate(); - } - - @Override - public JwtParser deserializeJsonWith(Deserializer> deserializer) { - throw doNotMutate(); - } - - @Override - public boolean isSigned(String compact) { - return this.jwtParser.isSigned(compact); - } - - @Override - public Jwt parse(String jwt) throws ExpiredJwtException, MalformedJwtException, SignatureException, IllegalArgumentException { - return this.jwtParser.parse(jwt); - } - - @Override - public T parse(String jwt, JwtHandler handler) throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException { - return this.jwtParser.parse(jwt, handler); - } - - @Override - public Jwt parseContentJwt(String jwt) throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException { - return this.jwtParser.parseContentJwt(jwt); - } - - @Override - public Jwt parseClaimsJwt(String jwt) throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException { - return this.jwtParser.parseClaimsJwt(jwt); - } - - @Override - public Jws parseContentJws(String jws) throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException { - return this.jwtParser.parseContentJws(jws); - } - - @Override - public Jws parseClaimsJws(String jws) throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException { - return this.jwtParser.parseClaimsJws(jws); - } - - @Override - public Jwe parseContentJwe(String jwe) throws JwtException { - return this.jwtParser.parseContentJwe(jwe); - } - - @Override - public Jwe parseClaimsJwe(String jwe) throws JwtException { - return this.jwtParser.parseClaimsJwe(jwe); - } -} diff --git a/impl/src/main/java/io/jsonwebtoken/impl/lang/LegacyServices.java b/impl/src/main/java/io/jsonwebtoken/impl/lang/LegacyServices.java deleted file mode 100644 index ec0e10486..000000000 --- a/impl/src/main/java/io/jsonwebtoken/impl/lang/LegacyServices.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright © 2019 jsonwebtoken.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.jsonwebtoken.impl.lang; - -import io.jsonwebtoken.lang.Classes; -import io.jsonwebtoken.lang.UnknownClassException; - -/** - * A backward compatibility {@link Services} utility to help migrate away from {@link Classes#newInstance(String)}. - * TODO: remove before v1.0 - * @deprecated use {@link Services} directly - */ -@Deprecated -public final class LegacyServices { - - /** - * Wraps {@code Services.loadFirst} and throws a {@link UnknownClassException} instead of a - * {@link UnavailableImplementationException} to retain the previous behavior. This method should be used when - * to retain the previous behavior of methods that throw an unchecked UnknownClassException. - * @param the type of object to return - * @param spi the class for which to find the first instance - * @return the first instance of type {@code T} found from a call to {@link Services#loadFirst(Class)} - */ - public static T loadFirst(Class spi) { - try { - return Services.loadFirst(spi); - } catch (UnavailableImplementationException e) { - throw new UnknownClassException(e.getMessage(), e); - } - } -} diff --git a/impl/src/main/java/io/jsonwebtoken/impl/security/ConstantKeyLocator.java b/impl/src/main/java/io/jsonwebtoken/impl/security/ConstantKeyLocator.java index 0189aa270..f97ccd50e 100644 --- a/impl/src/main/java/io/jsonwebtoken/impl/security/ConstantKeyLocator.java +++ b/impl/src/main/java/io/jsonwebtoken/impl/security/ConstantKeyLocator.java @@ -15,18 +15,15 @@ */ package io.jsonwebtoken.impl.security; -import io.jsonwebtoken.Claims; import io.jsonwebtoken.Header; import io.jsonwebtoken.JweHeader; import io.jsonwebtoken.JwsHeader; import io.jsonwebtoken.LocatorAdapter; -import io.jsonwebtoken.SigningKeyResolver; import io.jsonwebtoken.impl.lang.Function; import java.security.Key; -@SuppressWarnings("deprecation") -public class ConstantKeyLocator extends LocatorAdapter implements SigningKeyResolver, Function { +public class ConstantKeyLocator extends LocatorAdapter implements Function { private final Key jwsKey; private final Key jweKey; @@ -36,16 +33,6 @@ public ConstantKeyLocator(Key jwsKey, Key jweKey) { this.jweKey = jweKey; } - @Override - public Key resolveSigningKey(JwsHeader header, Claims claims) { - return locate(header); - } - - @Override - public Key resolveSigningKey(JwsHeader header, byte[] content) { - return locate(header); - } - @Override protected Key locate(JwsHeader header) { return this.jwsKey; diff --git a/impl/src/test/groovy/io/jsonwebtoken/CustomObjectDeserializationTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/CustomObjectDeserializationTest.groovy index 62069823b..e5de114a0 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/CustomObjectDeserializationTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/CustomObjectDeserializationTest.groovy @@ -37,13 +37,13 @@ class CustomObjectDeserializationTest { String jwtString = Jwts.builder().claim("cust", customBean).compact() // no custom deserialization, object is a map - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(jwtString) + Jwt jwt = Jwts.parser().enableUnsecuredJws().build().parseClaimsJwt(jwtString) assertNotNull jwt assertEquals jwt.getPayload().get('cust'), [key1: 'value1', key2: 42] // custom type for 'cust' claim Deserializer deserializer = new JacksonDeserializer([cust: CustomBean]) - jwt = Jwts.parserBuilder().enableUnsecuredJws().deserializeJsonWith(deserializer).build().parseClaimsJwt(jwtString) + jwt = Jwts.parser().enableUnsecuredJws().deserializeJsonWith(deserializer).build().parseClaimsJwt(jwtString) assertNotNull jwt CustomBean result = jwt.getPayload().get("cust", CustomBean) assertEquals customBean, result diff --git a/impl/src/test/groovy/io/jsonwebtoken/DeprecatedJwtParserTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/DeprecatedJwtParserTest.groovy deleted file mode 100644 index 0b5fbea7f..000000000 --- a/impl/src/test/groovy/io/jsonwebtoken/DeprecatedJwtParserTest.groovy +++ /dev/null @@ -1,1520 +0,0 @@ -/* - * Copyright (C) 2014 jsonwebtoken.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.jsonwebtoken - -import io.jsonwebtoken.impl.DefaultClock -import io.jsonwebtoken.impl.FixedClock -import io.jsonwebtoken.impl.JwtTokenizer -import io.jsonwebtoken.impl.security.TestKeys -import io.jsonwebtoken.io.Encoders -import io.jsonwebtoken.lang.Strings -import io.jsonwebtoken.security.SignatureException -import org.junit.Test - -import java.nio.charset.StandardCharsets -import java.security.SecureRandom - -import static io.jsonwebtoken.impl.DefaultJwtParser.INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE -import static io.jsonwebtoken.impl.DefaultJwtParser.MISSING_EXPECTED_CLAIM_MESSAGE_TEMPLATE -import static org.junit.Assert.* - -class DeprecatedJwtParserTest { - - private static final SecureRandom random = new SecureRandom() //doesn't need to be seeded - just testing - - protected static byte[] randomKey() { - //create random signing key for testing: - byte[] key = new byte[64] - random.nextBytes(key) - return key - } - - protected static String base64Url(String s) { - byte[] bytes = s.getBytes(Strings.UTF_8) - return Encoders.BASE64URL.encode(bytes) - } - - @Test - void testIsSignedWithNullArgument() { - assertFalse Jwts.parser().isSigned(null) - } - - @Test - void testIsSignedWithJunkArgument() { - assertFalse Jwts.parser().isSigned('hello') - } - - @Test - void testParseWithJunkArgument() { - - String junkPayload = '{;aklsjd;fkajsd;fkjasd;lfkj}' - - String bad = base64Url('{"alg":"none"}') + '.' + base64Url(junkPayload) + '.' - - try { - Jwts.parserBuilder().enableUnsecuredJws().build().parse(bad) - fail() - } catch (MalformedJwtException expected) { - assertEquals 'Unable to read claims JSON: ' + junkPayload, expected.getMessage() - } - } - - @Test - void testParseJwsWithBadAlgHeader() { - - String badAlgorithmName = 'whatever' - - String header = "{\"alg\":\"$badAlgorithmName\"}" - - String payload = '{"subject":"Joe"}' - - String badSig = ";aklsjdf;kajsd;fkjas;dklfj" - - String bad = base64Url(header) + '.' + base64Url(payload) + '.' + base64Url(badSig) - - try { - Jwts.parser().setSigningKey(randomKey()).parse(bad) - fail() - } catch (SignatureException se) { - assertEquals se.getMessage(), "Unsupported signature algorithm '$badAlgorithmName'".toString() - } - } - - @Test - void testParseWithInvalidSignature() { - - String header = '{"alg":"HS256"}' - - String payload = '{"subject":"Joe"}' - - String badSig = ";aklsjdf;kajsd;fkjas;dklfj" - - String bad = base64Url(header) + '.' + base64Url(payload) + '.' + base64Url(badSig) - - try { - Jwts.parserBuilder().setSigningKey(randomKey()).build().parse(bad) - fail() - } catch (SignatureException se) { - assertEquals se.getMessage(), 'JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.' - } - - } - - @Test - void testParseContentJwsWithIncorrectAlg() { - - def header = '{"alg":"none"}' - - def payload = '{"subject":"Joe"}' - - def badSig = ";aklsjdf;kajsd;fkjas;dklfj" - - String bad = base64Url(header) + '.' + base64Url(payload) + '.' + base64Url(badSig) - - try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(randomKey()).build().parse(bad) - fail() - } catch (MalformedJwtException se) { - assertEquals 'The JWS header references signature algorithm \'none\' yet the compact JWS string contains a signature. This is not permitted per https://tools.ietf.org/html/rfc7518#section-3.6.', se.getMessage() - } - - } - - @Test - void testParseWithBase64EncodedSigningKey() { - - byte[] key = randomKey() - - String base64Encodedkey = Encoders.BASE64.encode(key) - - String payload = 'Hello world!' - - //noinspection GrDeprecatedAPIUsage - String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, base64Encodedkey).compact() - - assertTrue Jwts.parser().isSigned(compact) - - def jwt = Jwts.parser().setSigningKey(base64Encodedkey).parse(compact) - - assertEquals payload, new String(jwt.body as byte[], StandardCharsets.UTF_8) - } - - @Test - void testParseWithExpiredJwt() { - - Date exp = new Date(System.currentTimeMillis() - 1000) - - String compact = Jwts.builder().setSubject('Joe').setExpiration(exp).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact) - fail() - } catch (ExpiredJwtException e) { - assertTrue e.getMessage().startsWith('JWT expired at ') - - //https://github.com/jwtk/jjwt/issues/107 (the Z designator at the end of the timestamp): - assertTrue e.getMessage().contains('Z, a difference of ') - } - } - - @Test - void testParseWithPrematureJwt() { - - Date nbf = new Date(System.currentTimeMillis() + 100000) - - String compact = Jwts.builder().setSubject('Joe').setNotBefore(nbf).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact) - fail() - } catch (PrematureJwtException e) { - assertTrue e.getMessage().startsWith('JWT must not be accepted before ') - - //https://github.com/jwtk/jjwt/issues/107 (the Z designator at the end of the timestamp): - assertTrue e.getMessage().contains('Z, a difference of ') - } - } - - @Test - void testParseWithExpiredJwtWithinAllowedClockSkew() { - Date exp = new Date(System.currentTimeMillis() - 3000) - - String subject = 'Joe' - String compact = Jwts.builder().setSubject(subject).setExpiration(exp).compact() - - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().setAllowedClockSkewSeconds(10).build().parse(compact) - - assertEquals jwt.getBody().getSubject(), subject - } - - @Test - void testParseWithExpiredJwtNotWithinAllowedClockSkew() { - Date exp = new Date(System.currentTimeMillis() - 3000) - - String compact = Jwts.builder().setSubject('Joe').setExpiration(exp).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().setAllowedClockSkewSeconds(1).build().parse(compact) - fail() - } catch (ExpiredJwtException e) { - assertTrue e.getMessage().startsWith('JWT expired at ') - } - } - - @Test - void testParseWithPrematureJwtWithinAllowedClockSkew() { - Date exp = new Date(System.currentTimeMillis() + 3000) - - String subject = 'Joe' - String compact = Jwts.builder().setSubject(subject).setNotBefore(exp).compact() - - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().setAllowedClockSkewSeconds(10).build().parse(compact) - - assertEquals jwt.getBody().getSubject(), subject - } - - @Test - void testParseWithPrematureJwtNotWithinAllowedClockSkew() { - Date exp = new Date(System.currentTimeMillis() + 3000) - - String compact = Jwts.builder().setSubject('Joe').setNotBefore(exp).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().setAllowedClockSkewSeconds(1).build().parse(compact) - fail() - } catch (PrematureJwtException e) { - assertTrue e.getMessage().startsWith('JWT must not be accepted before ') - } - } - - // ======================================================================== - // parseContentJwt tests - // ======================================================================== - - @Test - void testParseContentJwt() { - - String payload = 'Hello world!' - - String compact = Jwts.builder().setPayload(payload).compact() - - def jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseContentJwt(compact) - - assertEquals payload, new String(jwt.body, StandardCharsets.UTF_8) - } - - @Test - void testParseContentJwtWithClaimsJwt() { - - String compact = Jwts.builder().setSubject('Joe').compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().build().parseContentJwt(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals e.getMessage(), 'Unprotected Claims JWTs are not supported.' - } - } - - @Test - void testParseContentJwtWithContentJws() { - - String payload = 'Hello world!' - - String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, randomKey()).compact() - - try { - Jwts.parser().parseContentJwt(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Cannot verify JWS signature: unable to locate signature verification key for JWS with header: {alg=HS256}', e.getMessage() - } - } - - @Test - void testParseContentJwtWithClaimsJws() { - - String compact = Jwts.builder().setSubject('Joe').signWith(SignatureAlgorithm.HS256, randomKey()).compact() - - try { - Jwts.parser().parseContentJwt(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Cannot verify JWS signature: unable to locate signature verification key for JWS with header: {alg=HS256}', e.getMessage() - } - } - - // ======================================================================== - // parseClaimsJwt tests - // ======================================================================== - - @Test - void testParseClaimsJwt() { - - String subject = 'Joe' - - String compact = Jwts.builder().setSubject(subject).compact() - - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(compact) - - assertEquals jwt.getBody().getSubject(), subject - } - - @Test - void testParseClaimsJwtWithContentJwt() { - - String payload = 'Hello world!' - - String compact = Jwts.builder().setPayload(payload).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Unprotected content JWTs are not supported.', e.getMessage() - } - } - - @Test - void testParseClaimsJwtWithContentJws() { - - String payload = 'Hello world!' - - String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, randomKey()).compact() - - try { - Jwts.parser().parseClaimsJwt(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Cannot verify JWS signature: unable to locate signature verification key for JWS with header: {alg=HS256}', e.getMessage() - } - } - - @Test - void testParseClaimsJwtWithClaimsJws() { - - String compact = Jwts.builder().setSubject('Joe').signWith(SignatureAlgorithm.HS256, randomKey()).compact() - - try { - Jwts.parser().parseClaimsJwt(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Cannot verify JWS signature: unable to locate signature verification key for JWS with header: {alg=HS256}', e.getMessage() - } - } - - @Test - void testParseClaimsJwtWithExpiredJwt() { - - long nowMillis = System.currentTimeMillis() - //some time in the past: - Date exp = new Date(nowMillis - 1000) - - String compact = Jwts.builder().setSubject('Joe').setExpiration(exp).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(compact) - fail() - } catch (ExpiredJwtException e) { - assertTrue e.getMessage().startsWith('JWT expired at ') - } - } - - @Test - void testParseClaimsJwtWithPrematureJwt() { - - Date nbf = new Date(System.currentTimeMillis() + 100000) - - String compact = Jwts.builder().setSubject('Joe').setNotBefore(nbf).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(compact) - fail() - } catch (PrematureJwtException e) { - assertTrue e.getMessage().startsWith('JWT must not be accepted before ') - } - } - - // ======================================================================== - // parseContentJws tests - // ======================================================================== - - @Test - void testParseContentJws() { - - String payload = 'Hello world!' - - byte[] key = randomKey() - - String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, key).compact() - - def jwt = Jwts.parser().setSigningKey(key).parseContentJws(compact) - - assertEquals payload, new String(jwt.body, StandardCharsets.UTF_8) - } - - @Test - void testParseContentJwsWithContentJwt() { - - String payload = 'Hello world!' - - byte[] key = randomKey() - - String compact = Jwts.builder().setPayload(payload).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parseContentJws(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Unprotected content JWTs are not supported.', e.getMessage() - } - } - - @Test - void testParseContentJwsWithClaimsJwt() { - - String subject = 'Joe' - - byte[] key = randomKey() - - String compact = Jwts.builder().setSubject(subject).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parseContentJws(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Unprotected Claims JWTs are not supported.', e.getMessage() - } - } - - @Test - void testParseContentJwsWithClaimsJws() { - - String subject = 'Joe' - - byte[] key = randomKey() - - String compact = Jwts.builder().setSubject(subject).signWith(SignatureAlgorithm.HS256, key).compact() - - try { - Jwts.parser().setSigningKey(key).parseContentJws(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Signed Claims JWTs are not supported.', e.getMessage() - } - } - - // ======================================================================== - // parseClaimsJws tests - // ======================================================================== - - @Test - void testParseClaimsJws() { - - String sub = 'Joe' - - byte[] key = randomKey() - - String compact = Jwts.builder().setSubject(sub).signWith(SignatureAlgorithm.HS256, key).compact() - - Jwt jwt = Jwts.parser().setSigningKey(key).parseClaimsJws(compact) - - assertEquals jwt.getBody().getSubject(), sub - } - - @Test - void testParseClaimsJwsWithExpiredJws() { - - String sub = 'Joe' - - byte[] key = randomKey() - - long nowMillis = System.currentTimeMillis() - //some time in the past: - Date exp = new Date(nowMillis - 1000) - - String compact = Jwts.builder().setSubject(sub).signWith(SignatureAlgorithm.HS256, key).setExpiration(exp).compact() - - try { - Jwts.parser().setSigningKey(key).parseClaimsJwt(compact) - fail() - } catch (ExpiredJwtException e) { - assertTrue e.getMessage().startsWith('JWT expired at ') - assertEquals e.getClaims().getSubject(), sub - assertEquals e.getHeader().getAlgorithm(), "HS256" - } - } - - @Test - void testParseClaimsJwsWithPrematureJws() { - - String sub = 'Joe' - - byte[] key = randomKey() - - Date nbf = new Date(System.currentTimeMillis() + 100000) - - String compact = Jwts.builder().setSubject(sub).setNotBefore(nbf).signWith(SignatureAlgorithm.HS256, key).compact() - - try { - Jwts.parser().setSigningKey(key).parseClaimsJws(compact) - fail() - } catch (PrematureJwtException e) { - assertTrue e.getMessage().startsWith('JWT must not be accepted before ') - assertEquals e.getClaims().getSubject(), sub - assertEquals e.getHeader().getAlgorithm(), "HS256" - } - } - - @Test - void testParseClaimsJwsWithContentJwt() { - - String payload = 'Hello world!' - - byte[] key = randomKey() - - String compact = Jwts.builder().setPayload(payload).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parseClaimsJws(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Unprotected content JWTs are not supported.', e.getMessage() - } - } - - @Test - void testParseClaimsJwsWithClaimsJwt() { - - String subject = 'Joe' - - byte[] key = randomKey() - - String compact = Jwts.builder().setSubject(subject).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parseClaimsJws(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Unprotected Claims JWTs are not supported.', e.getMessage() - } - } - - @Test - void testParseClaimsJwsWithContentJws() { - - String payload = 'Hello world' - - byte[] key = randomKey() - - String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, key).compact() - - try { - Jwts.parser().setSigningKey(key).parseClaimsJws(compact) - fail() - } catch (UnsupportedJwtException e) { - assertEquals 'Signed content JWTs are not supported.', e.getMessage() - } - } - - // ======================================================================== - // parseClaimsJws with signingKey resolver. - // ======================================================================== - - @Test - void testParseClaimsWithSigningKeyResolver() { - - String subject = 'Joe' - - byte[] key = randomKey() - - String compact = Jwts.builder().setSubject(subject).signWith(SignatureAlgorithm.HS256, key).compact() - - def signingKeyResolver = new SigningKeyResolverAdapter() { - @Override - byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) { - return key - } - } - - Jws jws = Jwts.parser().setSigningKeyResolver(signingKeyResolver).parseClaimsJws(compact) - - assertEquals jws.getBody().getSubject(), subject - } - - @Test - void testParseClaimsWithSigningKeyResolverInvalidKey() { - - String subject = 'Joe' - - byte[] key = randomKey() - - String compact = Jwts.builder().setSubject(subject).signWith(SignatureAlgorithm.HS256, key).compact() - - def signingKeyResolver = new SigningKeyResolverAdapter() { - @Override - byte[] resolveSigningKeyBytes(JwsHeader header, Claims claims) { - return randomKey() - } - } - - try { - Jwts.parser().setSigningKeyResolver(signingKeyResolver).parseClaimsJws(compact) - fail() - } catch (SignatureException se) { - assertEquals se.getMessage(), 'JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.' - } - } - - @Test - void testParseClaimsWithNullSigningKeyResolver() { - - String subject = 'Joe' - - byte[] key = randomKey() - - String compact = Jwts.builder().setSubject(subject).signWith(SignatureAlgorithm.HS256, key).compact() - - try { - Jwts.parser().setSigningKeyResolver(null).parseClaimsJws(compact) - fail() - } catch (IllegalArgumentException iae) { - assertEquals iae.getMessage(), 'SigningKeyResolver cannot be null.' - } - } - - @Test - void testParseClaimsWithInvalidSigningKeyResolverAdapter() { - - String subject = 'Joe' - - byte[] key = randomKey() - - String compact = Jwts.builder().setSubject(subject).signWith(SignatureAlgorithm.HS256, key).compact() - - def signingKeyResolver = new SigningKeyResolverAdapter() - - try { - Jwts.parser().setSigningKeyResolver(signingKeyResolver).parseClaimsJws(compact) - fail() - } catch (UnsupportedJwtException ex) { - assertEquals ex.getMessage(), 'The specified SigningKeyResolver implementation does not support ' + - 'Claims JWS signing key resolution. Consider overriding either the resolveSigningKey(JwsHeader, Claims) method ' + - 'or, for HMAC algorithms, the resolveSigningKeyBytes(JwsHeader, Claims) method.' - } - } - - @Test - void testParseClaimsJwsWithNumericTypes() { - byte[] key = randomKey() - - def b = (byte) 42 - def s = (short) 42 - def i = 42 - - def smallLong = (long) 42 - def bigLong = ((long) Integer.MAX_VALUE) + 42 - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - claim("byte", b). - claim("short", s). - claim("int", i). - claim("long_small", smallLong). - claim("long_big", bigLong). - compact() - - Jwt jwt = Jwts.parser().setSigningKey(key).parseClaimsJws(compact) - - Claims claims = jwt.getBody() - - assertEquals(b, claims.get("byte", Byte.class)) - assertEquals(s, claims.get("short", Short.class)) - assertEquals(i, claims.get("int", Integer.class)) - assertEquals(smallLong, claims.get("long_small", Long.class)) - assertEquals(bigLong, claims.get("long_big", Long.class)) - } - - // ======================================================================== - // parseContentJws with signingKey resolver. - // ======================================================================== - - @Test - void testParseContentJwsWithSigningKeyResolverAdapter() { - - String inputPayload = 'Hello world!' - - byte[] key = randomKey() - - String compact = Jwts.builder().setPayload(inputPayload).signWith(SignatureAlgorithm.HS256, key).compact() - - def signingKeyResolver = new SigningKeyResolverAdapter() { - @Override - byte[] resolveSigningKeyBytes(JwsHeader header, byte[] payload) { - return key - } - } - - Jws jws = Jwts.parser().setSigningKeyResolver(signingKeyResolver).parseContentJws(compact) - - assertEquals inputPayload, new String(jws.body, StandardCharsets.UTF_8) - } - - @Test - void testParseContentJwsWithSigningKeyResolverInvalidKey() { - - byte[] inputPayload = 'Hello world!'.getBytes(StandardCharsets.UTF_8) - - byte[] key = randomKey() - - String compact = Jwts.builder().setContent(inputPayload).signWith(SignatureAlgorithm.HS256, key).compact() - - def signingKeyResolver = new SigningKeyResolverAdapter() { - @Override - byte[] resolveSigningKeyBytes(JwsHeader header, byte[] payload) { - return randomKey() - } - } - - try { - Jwts.parser().setSigningKeyResolver(signingKeyResolver).parseContentJws(compact) - fail() - } catch (SignatureException se) { - assertEquals se.getMessage(), 'JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.' - } - } - - @Test - void testParseContentJwsWithInvalidSigningKeyResolverAdapter() { - - String payload = 'Hello world!' - - byte[] key = randomKey() - - String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, key).compact() - - def signingKeyResolver = new SigningKeyResolverAdapter() - - try { - Jwts.parser().setSigningKeyResolver(signingKeyResolver).parseContentJws(compact) - fail() - } catch (UnsupportedJwtException ex) { - assertEquals ex.getMessage(), 'The specified SigningKeyResolver implementation does not support content ' + - 'JWS signing key resolution. Consider overriding either the resolveSigningKey(JwsHeader, byte[]) ' + - 'method or, for HMAC algorithms, the resolveSigningKeyBytes(JwsHeader, byte[]) method.' - } - } - - @Test - void testParseRequireDontAllowNullClaimName() { - def expectedClaimValue = 'A Most Awesome Claim Value' - - byte[] key = randomKey() - - // not setting expected claim name in JWT - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key).setIssuer('Dummy').compact() - - try { - // expecting null claim name, but with value - Jwts.parser().setSigningKey(key).require(null, expectedClaimValue).parseClaimsJws(compact) - fail() - } catch (IllegalArgumentException e) { - assertEquals( - "claim name cannot be null or empty.", - e.getMessage() - ) - } - } - - @Test - void testParseRequireDontAllowEmptyClaimName() { - def expectedClaimValue = 'A Most Awesome Claim Value' - - byte[] key = randomKey() - - // not setting expected claim name in JWT - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setIssuer('Dummy'). - compact() - - try { - // expecting null claim name, but with value - Jwt jwt = Jwts.parser().setSigningKey(key). - require("", expectedClaimValue). - parseClaimsJws(compact) - fail() - } catch (IllegalArgumentException e) { - assertEquals( - "claim name cannot be null or empty.", - e.getMessage() - ) - } - } - - @Test - void testParseRequireDontAllowNullClaimValue() { - def expectedClaimName = 'A Most Awesome Claim Name' - - byte[] key = randomKey() - - // not setting expected claim name in JWT - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key).setIssuer('Dummy').compact() - - try { - // expecting claim name, but with null value - Jwt jwt = Jwts.parser().setSigningKey(key). - require(expectedClaimName, null). - parseClaimsJws(compact) - fail() - } catch (IllegalArgumentException e) { - assertEquals( - "The value cannot be null for claim name: " + expectedClaimName, - e.getMessage() - ) - } - } - - @Test - void testParseRequireGeneric_Success() { - def expectedClaimName = 'A Most Awesome Claim Name' - def expectedClaimValue = 'A Most Awesome Claim Value' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - claim(expectedClaimName, expectedClaimValue). - compact() - - Jwt jwt = Jwts.parser().setSigningKey(key). - require(expectedClaimName, expectedClaimValue). - parseClaimsJws(compact) - - assertEquals jwt.getBody().get(expectedClaimName), expectedClaimValue - } - - @Test - void testParseRequireGeneric_Incorrect_Fail() { - def goodClaimName = 'A Most Awesome Claim Name' - def goodClaimValue = 'A Most Awesome Claim Value' - - def badClaimValue = 'A Most Bogus Claim Value' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - claim(goodClaimName, badClaimValue). - compact() - - try { - Jwts.parser().setSigningKey(key). - require(goodClaimName, goodClaimValue). - parseClaimsJws(compact) - fail() - } catch (IncorrectClaimException e) { - assertEquals( - String.format(INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE, goodClaimName, goodClaimValue, badClaimValue), - e.getMessage() - ) - } - } - - @Test - void testParseRequireedGeneric_Missing_Fail() { - def claimName = 'A Most Awesome Claim Name' - def claimValue = 'A Most Awesome Claim Value' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setIssuer('Dummy'). - compact() - - try { - Jwt jwt = Jwts.parser().setSigningKey(key). - require(claimName, claimValue). - parseClaimsJws(compact) - fail() - } catch (MissingClaimException e) { - assertEquals( - String.format(MISSING_EXPECTED_CLAIM_MESSAGE_TEMPLATE, claimName, claimValue), - e.getMessage() - ) - } - } - - @Test - void testParseRequireIssuedAt_Success() { - - def issuedAt = new Date(System.currentTimeMillis()) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setIssuedAt(issuedAt). - compact() - - Jwt jwt = Jwts.parser().setSigningKey(key). - requireIssuedAt(issuedAt). - parseClaimsJws(compact) - - assertEquals jwt.getBody().getIssuedAt().getTime(), truncateMillis(issuedAt) - } - - @Test(expected = IncorrectClaimException) - void testParseRequireIssuedAt_Incorrect_Fail() { - def goodIssuedAt = new Date(System.currentTimeMillis()) - def badIssuedAt = new Date(System.currentTimeMillis() - 10000) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setIssuedAt(badIssuedAt). - compact() - - Jwts.parser().setSigningKey(key). - requireIssuedAt(goodIssuedAt). - parseClaimsJws(compact) - } - - @Test(expected = MissingClaimException) - void testParseRequireIssuedAt_Missing_Fail() { - def issuedAt = new Date(System.currentTimeMillis() - 10000) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setSubject("Dummy"). - compact() - - Jwts.parser().setSigningKey(key). - requireIssuedAt(issuedAt). - parseClaimsJws(compact) - } - - @Test - void testParseRequireIssuer_Success() { - def issuer = 'A Most Awesome Issuer' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setIssuer(issuer). - compact() - - Jwt jwt = Jwts.parser().setSigningKey(key). - requireIssuer(issuer). - parseClaimsJws(compact) - - assertEquals jwt.getBody().getIssuer(), issuer - } - - @Test - void testParseRequireIssuer_Incorrect_Fail() { - def goodIssuer = 'A Most Awesome Issuer' - def badIssuer = 'A Most Bogus Issuer' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setIssuer(badIssuer). - compact() - - try { - Jwts.parser().setSigningKey(key). - requireIssuer(goodIssuer). - parseClaimsJws(compact) - fail() - } catch (IncorrectClaimException e) { - assertEquals( - String.format(INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE, Claims.ISSUER, goodIssuer, badIssuer), - e.getMessage() - ) - } - } - - @Test - void testParseRequireIssuer_Missing_Fail() { - def issuer = 'A Most Awesome Issuer' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setId('id'). - compact() - - try { - Jwts.parser().setSigningKey(key). - requireIssuer(issuer). - parseClaimsJws(compact) - fail() - } catch (MissingClaimException e) { - assertEquals( - String.format(MISSING_EXPECTED_CLAIM_MESSAGE_TEMPLATE, Claims.ISSUER, issuer), - e.getMessage() - ) - } - } - - @Test - void testParseRequireAudience_Success() { - def audience = 'A Most Awesome Audience' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setAudience(audience). - compact() - - Jwt jwt = Jwts.parser().setSigningKey(key). - requireAudience(audience). - parseClaimsJws(compact) - - assertEquals jwt.getBody().getAudience(), audience - } - - @Test - void testParseRequireAudience_Incorrect_Fail() { - def goodAudience = 'A Most Awesome Audience' - def badAudience = 'A Most Bogus Audience' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setAudience(badAudience). - compact() - - try { - Jwts.parser().setSigningKey(key). - requireAudience(goodAudience). - parseClaimsJws(compact) - fail() - } catch (IncorrectClaimException e) { - assertEquals( - String.format(INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE, Claims.AUDIENCE, goodAudience, badAudience), - e.getMessage() - ) - } - } - - @Test - void testParseRequireAudience_Missing_Fail() { - def audience = 'A Most Awesome audience' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setId('id'). - compact() - - try { - Jwts.parser().setSigningKey(key). - requireAudience(audience). - parseClaimsJws(compact) - fail() - } catch (MissingClaimException e) { - assertEquals( - String.format(MISSING_EXPECTED_CLAIM_MESSAGE_TEMPLATE, Claims.AUDIENCE, audience), - e.getMessage() - ) - } - } - - @Test - void testParseRequireSubject_Success() { - def subject = 'A Most Awesome Subject' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setSubject(subject). - compact() - - Jwt jwt = Jwts.parser().setSigningKey(key). - requireSubject(subject). - parseClaimsJws(compact) - - assertEquals jwt.getBody().getSubject(), subject - } - - @Test - void testParseRequireSubject_Incorrect_Fail() { - def goodSubject = 'A Most Awesome Subject' - def badSubject = 'A Most Bogus Subject' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setSubject(badSubject). - compact() - - try { - Jwts.parser().setSigningKey(key). - requireSubject(goodSubject). - parseClaimsJws(compact) - fail() - } catch (IncorrectClaimException e) { - assertEquals( - String.format(INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE, Claims.SUBJECT, goodSubject, badSubject), - e.getMessage() - ) - } - } - - @Test - void testParseRequireSubject_Missing_Fail() { - def subject = 'A Most Awesome Subject' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setId('id'). - compact() - - try { - Jwts.parser().setSigningKey(key). - requireSubject(subject). - parseClaimsJws(compact) - fail() - } catch (MissingClaimException e) { - assertEquals( - String.format(MISSING_EXPECTED_CLAIM_MESSAGE_TEMPLATE, Claims.SUBJECT, subject), - e.getMessage() - ) - } - } - - @Test - void testParseRequireId_Success() { - def id = 'A Most Awesome id' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setId(id). - compact() - - Jwt jwt = Jwts.parser().setSigningKey(key). - requireId(id). - parseClaimsJws(compact) - - assertEquals jwt.getBody().getId(), id - } - - @Test - void testParseRequireId_Incorrect_Fail() { - def goodId = 'A Most Awesome Id' - def badId = 'A Most Bogus Id' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setId(badId). - compact() - - try { - Jwts.parser().setSigningKey(key). - requireId(goodId). - parseClaimsJws(compact) - fail() - } catch (IncorrectClaimException e) { - assertEquals( - String.format(INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE, Claims.ID, goodId, badId), - e.getMessage() - ) - } - } - - @Test - void testParseRequireId_Missing_Fail() { - def id = 'A Most Awesome Id' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setIssuer('me'). - compact() - - try { - Jwts.parser().setSigningKey(key). - requireId(id). - parseClaimsJws(compact) - fail() - } catch (MissingClaimException e) { - assertEquals( - String.format(MISSING_EXPECTED_CLAIM_MESSAGE_TEMPLATE, Claims.ID, id), - e.getMessage() - ) - } - } - - @Test - void testParseRequireExpiration_Success() { - // expire in the future - def expiration = new Date(System.currentTimeMillis() + 10000) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setExpiration(expiration). - compact() - - Jwt jwt = Jwts.parser().setSigningKey(key). - requireExpiration(expiration). - parseClaimsJws(compact) - - assertEquals jwt.getBody().getExpiration().getTime(), truncateMillis(expiration) - } - - @Test(expected = IncorrectClaimException) - void testParseRequireExpirationAt_Incorrect_Fail() { - def goodExpiration = new Date(System.currentTimeMillis() + 20000) - def badExpiration = new Date(System.currentTimeMillis() + 10000) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setExpiration(badExpiration). - compact() - - Jwts.parser().setSigningKey(key). - requireExpiration(goodExpiration). - parseClaimsJws(compact) - } - - @Test(expected = MissingClaimException) - void testParseRequireExpiration_Missing_Fail() { - def expiration = new Date(System.currentTimeMillis() + 10000) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setSubject("Dummy"). - compact() - - Jwts.parser().setSigningKey(key). - requireExpiration(expiration). - parseClaimsJws(compact) - } - - @Test - void testParseRequireNotBefore_Success() { - // expire in the future - def notBefore = new Date(System.currentTimeMillis() - 10000) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setNotBefore(notBefore). - compact() - - Jwt jwt = Jwts.parser().setSigningKey(key). - requireNotBefore(notBefore). - parseClaimsJws(compact) - - assertEquals jwt.getBody().getNotBefore().getTime(), truncateMillis(notBefore) - } - - @Test(expected = IncorrectClaimException) - void testParseRequireNotBefore_Incorrect_Fail() { - def goodNotBefore = new Date(System.currentTimeMillis() - 20000) - def badNotBefore = new Date(System.currentTimeMillis() - 10000) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setNotBefore(badNotBefore). - compact() - - Jwts.parser().setSigningKey(key). - requireNotBefore(goodNotBefore). - parseClaimsJws(compact) - } - - @Test(expected = MissingClaimException) - void testParseRequireNotBefore_Missing_Fail() { - def notBefore = new Date(System.currentTimeMillis() - 10000) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setSubject("Dummy"). - compact() - - Jwts.parser().setSigningKey(key). - requireNotBefore(notBefore). - parseClaimsJws(compact) - } - - @Test - void testParseRequireCustomDate_Success() { - - def aDate = new Date(System.currentTimeMillis()) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - claim("aDate", aDate). - compact() - - Jwt jwt = Jwts.parser().setSigningKey(key). - require("aDate", aDate). - parseClaimsJws(compact) - - assertEquals jwt.getBody().get("aDate", Date.class), aDate - } - - @Test - //since 0.10.0 - void testParseRequireCustomDateWhenClaimIsNotADate() { - - def goodDate = new Date(System.currentTimeMillis()) - def badDate = 'hello' - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - claim("aDate", badDate). - compact() - - try { - Jwts.parser().setSigningKey(key). - require("aDate", goodDate). - parseClaimsJws(compact) - fail() - } catch (IncorrectClaimException e) { - String expected = 'JWT Claim \'aDate\' was expected to be a Date, but its value cannot be converted to a ' + - 'Date using current heuristics. Value: hello' - assertEquals expected, e.getMessage() - } - } - - @Test - void testParseRequireCustomDate_Incorrect_Fail() { - - def goodDate = new Date(System.currentTimeMillis()) - def badDate = new Date(System.currentTimeMillis() - 10000) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - claim("aDate", badDate). - compact() - - try { - Jwts.parser().setSigningKey(key). - require("aDate", goodDate). - parseClaimsJws(compact) - fail() - } catch (IncorrectClaimException e) { - assertEquals( - String.format(INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE, "aDate", goodDate, badDate), - e.getMessage() - ) - } - } - - @Test - void testParseRequireCustomDate_Missing_Fail() { - def aDate = new Date(System.currentTimeMillis()) - - byte[] key = randomKey() - - String compact = Jwts.builder().signWith(SignatureAlgorithm.HS256, key). - setSubject("Dummy"). - compact() - - try { - Jwts.parser().setSigningKey(key). - require("aDate", aDate). - parseClaimsJws(compact) - fail() - } catch (MissingClaimException e) { - assertEquals( - String.format(MISSING_EXPECTED_CLAIM_MESSAGE_TEMPLATE, "aDate", aDate), - e.getMessage() - ) - } - } - - @Test - void testParseClockManipulationWithFixedClock() { - def then = System.currentTimeMillis() - 1000 - Date expiry = new Date(then) - Date beforeExpiry = new Date(then - 1000) - - String compact = Jwts.builder().setSubject('Joe').setExpiration(expiry).compact() - - Jwts.parserBuilder().enableUnsecuredJws().setClock(new FixedClock(beforeExpiry)).build().parse(compact) - } - - @Test - void testParseClockManipulationWithNullClock() { - JwtParser parser = Jwts.parser(); - try { - parser.setClock(null) - fail() - } catch (IllegalArgumentException expected) { - } - } - - @Test - void testSetClock() { - def clock = new DefaultClock(); - def parser = Jwts.parser().setClock(clock) - assertSame clock, parser.@clock - assertFalse DefaultClock.INSTANCE.is(parser.@clock) - } - - @Test - void testParseClockManipulationWithDefaultClock() { - Date expiry = new Date(System.currentTimeMillis() - 1000) - - def key = TestKeys.HS256 - - String compact = Jwts.builder().setSubject('Joe').setExpiration(expiry) - .signWith(key).compact() - - try { - def clock = new DefaultClock() - def parser = Jwts.parser().setSigningKey(key).setClock(clock) - parser.parseClaimsJws(compact) - fail() - } catch (ExpiredJwtException e) { - assertTrue e.getMessage().startsWith('JWT expired at ') - } - } - - @Test - void testBuilderParseClockManipulationWithDefaultClock() { - Date expiry = new Date(System.currentTimeMillis() - 1000) - - String compact = Jwts.builder().setSubject('Joe').setExpiration(expiry).compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().setClock(new DefaultClock()).build().parse(compact) - fail() - } catch (ExpiredJwtException e) { - assertTrue e.getMessage().startsWith('JWT expired at ') - } - } - - @Test - void testParseMalformedJwt() { - - String header = '{"alg":"none"}' - - String payload = '{"subject":"Joe"}' - - String badSig = ";aklsjdf;kajsd;fkjas;dklfj" - - String bogus = 'bogus' - - String bad = base64Url(header) + '.' + base64Url(payload) + '.' + base64Url(badSig) + '.' + base64Url(bogus) - - try { - Jwts.parser().setSigningKey(randomKey()).parse(bad) - fail() - } catch (MalformedJwtException se) { - String expected = JwtTokenizer.DELIM_ERR_MSG_PREFIX + '3' - assertEquals expected, se.message - } - } - - @Test - void testNoProtectedHeader() { - - String payload = '{"sub":"Joe"}' - - String jwtStr = '.' + base64Url(payload) + '.' - - try { - Jwts.parserBuilder().build().parse(jwtStr) - fail() - } catch (MalformedJwtException e) { - assertEquals 'Compact JWT strings MUST always have a Base64Url protected header per https://tools.ietf.org/html/rfc7519#section-7.2 (steps 2-4).', e.getMessage() - } - } - - @Test - void testBadHeaderSig() { - - String header = '{"alg":"none"}' - - String payload = '{"subject":"Joe"}' - - String sig = ";aklsjdf;kajsd;fkjas;dklfj" - - String jwtStr = base64Url(header) + '.' + base64Url(payload) + '.' + base64Url(sig) - - try { - Jwts.parserBuilder().enableUnsecuredJws().build().parse(jwtStr) - fail() - } catch (MalformedJwtException se) { - assertEquals 'The JWS header references signature algorithm \'none\' yet the compact JWS string contains a signature. This is not permitted per https://tools.ietf.org/html/rfc7518#section-3.6.', se.message - } - } - - /** - * Date util method for lopping truncate the millis from a date. - * @param date input date - * @return The date time in millis with the precision of seconds - */ - private long truncateMillis(Date date) { - Calendar cal = Calendar.getInstance() - cal.setTime(date) - cal.set(Calendar.MILLISECOND, 0) - return cal.getTimeInMillis() - } -} diff --git a/impl/src/test/groovy/io/jsonwebtoken/DeprecatedJwtsTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/DeprecatedJwtsTest.groovy deleted file mode 100644 index 93f81801d..000000000 --- a/impl/src/test/groovy/io/jsonwebtoken/DeprecatedJwtsTest.groovy +++ /dev/null @@ -1,767 +0,0 @@ -/* - * Copyright (C) 2014 jsonwebtoken.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.jsonwebtoken - -import io.jsonwebtoken.impl.DefaultHeader -import io.jsonwebtoken.impl.DefaultJwsHeader -import io.jsonwebtoken.impl.JwtTokenizer -import io.jsonwebtoken.impl.compression.GzipCompressionAlgorithm -import io.jsonwebtoken.impl.lang.Services -import io.jsonwebtoken.impl.security.TestKeys -import io.jsonwebtoken.io.Encoders -import io.jsonwebtoken.io.Serializer -import io.jsonwebtoken.lang.Strings -import io.jsonwebtoken.security.Keys -import io.jsonwebtoken.security.WeakKeyException -import org.junit.Test - -import javax.crypto.Mac -import javax.crypto.spec.SecretKeySpec -import java.nio.charset.Charset -import java.security.KeyPair -import java.security.PrivateKey -import java.security.PublicKey - -import static org.junit.Assert.* - -@SuppressWarnings(['GrDeprecatedAPIUsage', 'GrUnnecessarySemicolon']) -class DeprecatedJwtsTest { - - private static Date now() { - return dateWithOnlySecondPrecision(System.currentTimeMillis()); - } - - private static int later() { - def date = laterDate(10000) - def seconds = date.getTime() / 1000 - return seconds as int - } - - private static Date laterDate(int seconds) { - def millis = seconds * 1000L - def time = System.currentTimeMillis() + millis - return dateWithOnlySecondPrecision(time) - } - - private static Date dateWithOnlySecondPrecision(long millis) { - long seconds = (millis / 1000) as long - long secondOnlyPrecisionMillis = seconds * 1000 - return new Date(secondOnlyPrecisionMillis) - } - - protected static String base64Url(String s) { - byte[] bytes = s.getBytes(Strings.UTF_8) - return Encoders.BASE64URL.encode(bytes) - } - - protected static String toJson(o) { - def serializer = Services.loadFirst(Serializer) - byte[] bytes = serializer.serialize(o) - return new String(bytes, Strings.UTF_8) - } - - @Test - void testSubclass() { - new Jwts() - } - - @Test - void testHeaderWithNoArgs() { - def header = Jwts.header().build() - assertTrue header instanceof DefaultHeader - } - - @Test - void testHeaderWithMapArg() { - def header = Jwts.header().set([alg: "HS256"]).build() - assertTrue header instanceof DefaultJwsHeader - assertEquals 'HS256', header.getAlgorithm() - assertEquals 'HS256', header.alg - } - - @Test - void testClaims() { - Claims claims = Jwts.claims().build() - assertNotNull claims - } - - @Test - void testClaimsWithMapArg() { - Claims claims = Jwts.claims([sub: 'Joe']) - assertNotNull claims - assertEquals claims.getSubject(), 'Joe' - } - - @Test - void testContentJwtString() { - - // Assert exact output per example at https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25#section-6.1 - - // The base64url encoding of the example claims set in the spec shows that their original payload ends lines with - // carriage return + newline, so we have to include them in the test payload to assert our encoded output - // matches what is in the spec: - - //noinspection HttpUrlsUsage - def payload = '{"iss":"joe",\r\n' + - ' "exp":1300819380,\r\n' + - ' "http://example.com/is_root":true}' - - String val = Jwts.builder().setPayload(payload).compact(); - - def specOutput = 'eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.' - - assertEquals val, specOutput - } - - @Test - void testParseContentToken() { - - def claims = [iss: 'joe', exp: later(), 'http://example.com/is_root': true] - - String jwt = Jwts.builder().setClaims(claims).compact(); - - def token = Jwts.parserBuilder().enableUnsecuredJws().build().parse(jwt); - - //noinspection GrEqualsBetweenInconvertibleTypes - assert token.body == claims - } - - @Test(expected = IllegalArgumentException) - void testParseNull() { - Jwts.parser().parse(null) - } - - @Test(expected = IllegalArgumentException) - void testParseEmptyString() { - Jwts.parser().parse('') - } - - @Test(expected = IllegalArgumentException) - void testParseWhitespaceString() { - Jwts.parser().parse(' ') - } - - @Test - void testParseWithNoPeriods() { - try { - Jwts.parser().parse('foo') - fail() - } catch (MalformedJwtException e) { - String expected = JwtTokenizer.DELIM_ERR_MSG_PREFIX + '0' - assertEquals expected, e.message - } - } - - @Test - void testParseWithOnePeriodOnly() { - try { - Jwts.parser().parse('.') - fail() - } catch (MalformedJwtException e) { - String expected = JwtTokenizer.DELIM_ERR_MSG_PREFIX + '1' - assertEquals expected, e.message - } - } - - @Test(expected = MalformedJwtException) - void testParseWithTwoPeriodsOnly() { - Jwts.parser().parse('..') - } - - @Test - void testParseWithHeaderOnly() { - String unsecuredJwt = base64Url("{\"alg\":\"none\"}") + ".." - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parse(unsecuredJwt) - assertEquals("none", jwt.getHeader().get("alg")) - } - - @Test(expected = MalformedJwtException) - void testParseWithSignatureOnly() { - Jwts.parser().parse('..bar') - } - - @Test - void testConvenienceIssuer() { - String compact = Jwts.builder().setIssuer("Me").compact(); - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertEquals claims.getIssuer(), "Me" - - compact = Jwts.builder().setSubject("Joe") - .setIssuer("Me") //set it - .setIssuer(null) //null should remove it - .compact(); - - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertNull claims.getIssuer() - } - - @Test - void testConvenienceSubject() { - String compact = Jwts.builder().setSubject("Joe").compact(); - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertEquals claims.getSubject(), "Joe" - - compact = Jwts.builder().setIssuer("Me") - .setSubject("Joe") //set it - .setSubject(null) //null should remove it - .compact(); - - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertNull claims.getSubject() - } - - @Test - void testConvenienceAudience() { - String compact = Jwts.builder().setAudience("You").compact(); - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertEquals claims.getAudience(), "You" - - compact = Jwts.builder().setIssuer("Me") - .setAudience("You") //set it - .setAudience(null) //null should remove it - .compact(); - - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertNull claims.getAudience() - } - - @Test - void testConvenienceExpiration() { - Date then = laterDate(10000) - String compact = Jwts.builder().setExpiration(then).compact(); - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - def claimedDate = claims.getExpiration() - assertEquals claimedDate, then - - compact = Jwts.builder().setIssuer("Me") - .setExpiration(then) //set it - .setExpiration(null) //null should remove it - .compact(); - - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertNull claims.getExpiration() - } - - @Test - void testConvenienceNotBefore() { - Date now = now() //jwt exp only supports *seconds* since epoch: - String compact = Jwts.builder().setNotBefore(now).compact(); - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - def claimedDate = claims.getNotBefore() - assertEquals claimedDate, now - - compact = Jwts.builder().setIssuer("Me") - .setNotBefore(now) //set it - .setNotBefore(null) //null should remove it - .compact(); - - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertNull claims.getNotBefore() - } - - @Test - void testConvenienceIssuedAt() { - Date now = now() //jwt exp only supports *seconds* since epoch: - String compact = Jwts.builder().setIssuedAt(now).compact(); - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - def claimedDate = claims.getIssuedAt() - assertEquals claimedDate, now - - compact = Jwts.builder().setIssuer("Me") - .setIssuedAt(now) //set it - .setIssuedAt(null) //null should remove it - .compact(); - - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertNull claims.getIssuedAt() - } - - @Test - void testConvenienceId() { - String id = UUID.randomUUID().toString(); - String compact = Jwts.builder().setId(id).compact(); - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertEquals claims.getId(), id - - compact = Jwts.builder().setIssuer("Me") - .setId(id) //set it - .setId(null) //null should remove it - .compact(); - - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).body as Claims - assertNull claims.getId() - } - - @Test - void testUncompressedJwt() { - - SignatureAlgorithm alg = SignatureAlgorithm.HS256 - byte[] key = Keys.secretKeyFor(alg).encoded - - String id = UUID.randomUUID().toString() - - String compact = Jwts.builder().setId(id).setAudience("an audience").signWith(alg, key) - .claim("state", "hello this is an amazing jwt").compact() - - def jws = Jwts.parser().setSigningKey(key).parseClaimsJws(compact) - - Claims claims = jws.body - - assertNull jws.header.getCompressionAlgorithm() - - assertEquals id, claims.getId() - assertEquals "an audience", claims.getAudience() - assertEquals "hello this is an amazing jwt", claims.state - } - - @Test - void testCompressedJwtWithDeflate() { - - SignatureAlgorithm alg = SignatureAlgorithm.HS256 - byte[] key = Keys.secretKeyFor(alg).encoded - - String id = UUID.randomUUID().toString() - - String compact = Jwts.builder().setId(id).setAudience("an audience").signWith(alg, key) - .claim("state", "hello this is an amazing jwt").compressWith(Jwts.ZIP.DEF).compact() - - def jws = Jwts.parser().setSigningKey(key).parseClaimsJws(compact) - - Claims claims = jws.body - - assertEquals "DEF", jws.header.getCompressionAlgorithm() - - assertEquals id, claims.getId() - assertEquals "an audience", claims.getAudience() - assertEquals "hello this is an amazing jwt", claims.state - } - - @Test - void testCompressedJwtWithGZIP() { - - SignatureAlgorithm alg = SignatureAlgorithm.HS256 - byte[] key = Keys.secretKeyFor(alg).encoded - - String id = UUID.randomUUID().toString() - - String compact = Jwts.builder().setId(id).setAudience("an audience").signWith(alg, key) - .claim("state", "hello this is an amazing jwt").compressWith(Jwts.ZIP.GZIP).compact() - - def jws = Jwts.parser().setSigningKey(key).parseClaimsJws(compact) - - Claims claims = jws.body - - assertEquals "GZIP", jws.header.getCompressionAlgorithm() - - assertEquals id, claims.getId() - assertEquals "an audience", claims.getAudience() - assertEquals "hello this is an amazing jwt", claims.state - } - - @Test - void testCompressedWithCustomResolver() { - - SignatureAlgorithm alg = SignatureAlgorithm.HS256 - byte[] key = Keys.secretKeyFor(alg).encoded - - String id = UUID.randomUUID().toString() - - String compact = Jwts.builder().setId(id).setAudience("an audience").signWith(alg, key) - .claim("state", "hello this is an amazing jwt").compressWith(new GzipCompressionAlgorithm() { - @Override - String getId() { - return "CUSTOM" - } - }).compact() - - def jws = Jwts.parser().setSigningKey(key).setCompressionCodecResolver(new CompressionCodecResolver() { - @Override - CompressionCodec resolveCompressionCodec(Header header) throws CompressionException { - String algorithm = header.getCompressionAlgorithm() - //noinspection ChangeToOperator - if ("CUSTOM".equals(algorithm)) { - return Jwts.ZIP.GZIP as CompressionCodec - } else { - return null - } - } - }).parseClaimsJws(compact) - - Claims claims = jws.body - - assertEquals "CUSTOM", jws.header.getCompressionAlgorithm() - - assertEquals id, claims.getId() - assertEquals "an audience", claims.getAudience() - assertEquals "hello this is an amazing jwt", claims.state - - } - - @Test(expected = UnsupportedJwtException.class) - void testCompressedJwtWithUnrecognizedHeader() { - - SignatureAlgorithm alg = SignatureAlgorithm.HS256 - byte[] key = Keys.secretKeyFor(alg).encoded - - String id = UUID.randomUUID().toString() - - String compact = Jwts.builder().setId(id).setAudience("an audience").signWith(alg, key) - .claim("state", "hello this is an amazing jwt").compressWith(new GzipCompressionAlgorithm() { - @Override - String getId() { - return "CUSTOM" - } - }).compact() - - Jwts.parser().setSigningKey(key).parseClaimsJws(compact) - } - - @Test - void testCompressStringPayloadWithDeflate() { - - SignatureAlgorithm alg = SignatureAlgorithm.HS256 - byte[] key = Keys.secretKeyFor(alg).encoded - - String payload = "this is my test for a payload" - - String compact = Jwts.builder().setPayload(payload).signWith(alg, key) - .compressWith(Jwts.ZIP.DEF).compact() - - def jws = Jwts.parser().setSigningKey(key).parseContentJws(compact) - - byte[] parsed = jws.body - - assertEquals "DEF", jws.header.getCompressionAlgorithm() - - assertEquals "this is my test for a payload", Strings.utf8(parsed) - } - - @Test - void testHS256() { - testHmac(SignatureAlgorithm.HS256) - } - - @Test - void testHS384() { - testHmac(SignatureAlgorithm.HS384) - } - - @Test - void testHS512() { - testHmac(SignatureAlgorithm.HS512) - } - - @Test - void testRS256() { - testRsa(SignatureAlgorithm.RS256) - } - - @Test - void testRS384() { - testRsa(SignatureAlgorithm.RS384) - } - - @Test - void testRS512() { - testRsa(SignatureAlgorithm.RS512) - } - - @Test - void testPS256() { - testRsa(SignatureAlgorithm.PS256) - } - - @Test - void testPS384() { - testRsa(SignatureAlgorithm.PS384) - } - - @Test - void testPS512() { - testRsa(SignatureAlgorithm.PS512) - } - - @Test - void testRSA256WithPrivateKeyValidation() { - testRsa(SignatureAlgorithm.RS256, true) - } - - @Test - void testRSA384WithPrivateKeyValidation() { - testRsa(SignatureAlgorithm.RS384, true) - } - - @Test - void testRSA512WithPrivateKeyValidation() { - testRsa(SignatureAlgorithm.RS512, true) - } - - @Test - void testES256() { - testEC(SignatureAlgorithm.ES256) - } - - @Test - void testES384() { - testEC(SignatureAlgorithm.ES384) - } - - @Test - void testES512() { - testEC(SignatureAlgorithm.ES512) - } - - @Test - void testES256WithPrivateKeyValidation() { - def alg = SignatureAlgorithm.ES256; - try { - testEC(alg, true) - fail("EC private keys cannot be used to validate EC signatures.") - } catch (UnsupportedJwtException e) { - String msg = "${alg.name()} verification keys must be PublicKeys (implement java.security.PublicKey). " + - "Provided key type: sun.security.ec.ECPrivateKeyImpl." - assertEquals msg, e.cause.message - } - } - - @Test - void testParseClaimsJwsWithWeakHmacKey() { - - SignatureAlgorithm alg = SignatureAlgorithm.HS384 - def key = Keys.secretKeyFor(alg) - def weakKey = Keys.secretKeyFor(SignatureAlgorithm.HS256) - - String jws = Jwts.builder().setSubject("Foo").signWith(key, alg).compact() - - //noinspection GroovyUnusedCatchParameter - try { - Jwts.parser().setSigningKey(weakKey).parseClaimsJws(jws) - fail('parseClaimsJws must fail for weak keys') - } catch (WeakKeyException expected) { - } - } - - //Asserts correct/expected behavior discussed in https://github.com/jwtk/jjwt/issues/20 - @Test - void testParseClaimsJwsWithUnsignedJwt() { - - //create random signing key for testing: - SignatureAlgorithm alg = SignatureAlgorithm.HS256 - byte[] key = Keys.secretKeyFor(alg).encoded - - String notSigned = Jwts.builder().setSubject("Foo").compact() - - try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parseClaimsJws(notSigned) - fail('parseClaimsJws must fail for unsigned JWTs') - } catch (UnsupportedJwtException expected) { - assertEquals 'Unprotected Claims JWTs are not supported.', expected.message - } - } - - //Asserts correct/expected behavior discussed in https://github.com/jwtk/jjwt/issues/20 - @Test - void testForgedTokenWithSwappedHeaderUsingNoneAlgorithm() { - - //create random signing key for testing: - SignatureAlgorithm alg = SignatureAlgorithm.HS256 - byte[] key = Keys.secretKeyFor(alg).encoded - - //this is a 'real', valid JWT: - String compact = Jwts.builder().setSubject("Joe").signWith(alg, key).compact() - - //Now strip off the signature so we can add it back in later on a forged token: - int i = compact.lastIndexOf('.') - String signature = compact.substring(i + 1) - - //now let's create a fake header and payload with whatever we want (without signing): - String forged = Jwts.builder().setSubject("Not Joe").compact() - - //assert that our forged header has a 'NONE' algorithm: - assertEquals 'none', Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(forged).getHeader().get('alg') - - //now let's forge it by appending the signature the server expects: - forged += signature - - //now assert that, when the server tries to parse the forged token, parsing fails: - try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parse(forged) - fail("Parsing must fail for a forged token.") - } catch (MalformedJwtException expected) { - assertEquals 'The JWS header references signature algorithm \'none\' yet the compact JWS string contains a signature. This is not permitted per https://tools.ietf.org/html/rfc7518#section-3.6.', expected.message - } - } - - //Asserts correct/expected behavior discussed in https://github.com/jwtk/jjwt/issues/20 and https://github.com/jwtk/jjwt/issues/25 - @Test - void testParseForgedRsaPublicKeyAsHmacTokenVerifiedWithTheRsaPrivateKey() { - - //Create a legitimate RSA public and private key pair: - KeyPair kp = TestKeys.RS256.pair - PublicKey publicKey = kp.getPublic() - PrivateKey privateKey = kp.getPrivate() - - String header = base64Url(toJson(['alg': 'HS256'])) - String body = base64Url(toJson('foo')) - String compact = header + '.' + body + '.' - - // Now for the forgery: simulate an attacker using the RSA public key to sign a token, but - // using it as an HMAC signing key instead of RSA: - Mac mac = Mac.getInstance('HmacSHA256'); - mac.init(new SecretKeySpec(publicKey.getEncoded(), 'HmacSHA256')); - byte[] signatureBytes = mac.doFinal(compact.getBytes(Charset.forName('US-ASCII'))) - String encodedSignature = Encoders.BASE64URL.encode(signatureBytes) - - //Finally, the forged token is the header + body + forged signature: - String forged = compact + encodedSignature; - - // Assert that the server (that should always use the private key) does not recognized the forged token: - try { - Jwts.parser().setSigningKey(privateKey).parse(forged); - fail("Forged token must not be successfully parsed.") - } catch (UnsupportedJwtException expected) { - assertTrue expected.getMessage().startsWith('The parsed JWT indicates it was signed with the') - } - } - - //Asserts correct behavior for https://github.com/jwtk/jjwt/issues/25 - @Test - void testParseForgedRsaPublicKeyAsHmacTokenVerifiedWithTheRsaPublicKey() { - - //Create a legitimate RSA public and private key pair: - KeyPair kp = TestKeys.RS256.pair - PublicKey publicKey = kp.getPublic(); - //PrivateKey privateKey = kp.getPrivate(); - - String header = base64Url(toJson(['alg': 'HS256'])) - String body = base64Url(toJson('foo')) - String compact = header + '.' + body + '.' - - // Now for the forgery: simulate an attacker using the RSA public key to sign a token, but - // using it as an HMAC signing key instead of RSA: - Mac mac = Mac.getInstance('HmacSHA256'); - mac.init(new SecretKeySpec(publicKey.getEncoded(), 'HmacSHA256')); - byte[] signatureBytes = mac.doFinal(compact.getBytes(Charset.forName('US-ASCII'))) - String encodedSignature = Encoders.BASE64URL.encode(signatureBytes); - - //Finally, the forged token is the header + body + forged signature: - String forged = compact + encodedSignature; - - // Assert that the parser does not recognized the forged token: - try { - Jwts.parser().setSigningKey(publicKey).parse(forged); - fail("Forged token must not be successfully parsed.") - } catch (UnsupportedJwtException expected) { - assertTrue expected.getMessage().startsWith('The parsed JWT indicates it was signed with the') - } - } - - //Asserts correct behavior for https://github.com/jwtk/jjwt/issues/25 - @Test - void testParseForgedEllipticCurvePublicKeyAsHmacToken() { - - //Create a legitimate RSA public and private key pair: - KeyPair kp = TestKeys.ES256.pair - PublicKey publicKey = kp.getPublic(); - //PrivateKey privateKey = kp.getPrivate(); - - String header = base64Url(toJson(['alg': 'HS256'])) - String body = base64Url(toJson('foo')) - String compact = header + '.' + body + '.' - - // Now for the forgery: simulate an attacker using the Elliptic Curve public key to sign a token, but - // using it as an HMAC signing key instead of Elliptic Curve: - Mac mac = Mac.getInstance('HmacSHA256'); - mac.init(new SecretKeySpec(publicKey.getEncoded(), 'HmacSHA256')); - byte[] signatureBytes = mac.doFinal(compact.getBytes(Charset.forName('US-ASCII'))) - String encodedSignature = Encoders.BASE64URL.encode(signatureBytes); - - //Finally, the forged token is the header + body + forged signature: - String forged = compact + encodedSignature; - - // Assert that the parser does not recognized the forged token: - try { - Jwts.parser().setSigningKey(publicKey).parse(forged) - fail("Forged token must not be successfully parsed.") - } catch (UnsupportedJwtException expected) { - assertTrue expected.getMessage().startsWith('The parsed JWT indicates it was signed with the') - } - } - - static void testRsa(SignatureAlgorithm alg, boolean verifyWithPrivateKey = false) { - - KeyPair kp = Keys.keyPairFor(alg) - PublicKey publicKey = kp.getPublic() - PrivateKey privateKey = kp.getPrivate() - - def claims = [iss: 'joe', exp: later(), 'http://example.com/is_root': true] - - String jwt = Jwts.builder().setClaims(claims).signWith(privateKey, alg).compact() - - def key = publicKey - if (verifyWithPrivateKey) { - key = privateKey - } - - def token = Jwts.parser().setSigningKey(key).parse(jwt) - - //noinspection GrEqualsBetweenInconvertibleTypes - assert [alg: alg.name()] == token.header - //noinspection GrEqualsBetweenInconvertibleTypes - assert token.body == claims - } - - static void testHmac(SignatureAlgorithm alg) { - - //create random signing key for testing: - byte[] key = Keys.secretKeyFor(alg).encoded - - def claims = [iss: 'joe', exp: later(), 'http://example.com/is_root': true] - - String jwt = Jwts.builder().setClaims(claims).signWith(alg, key).compact() - - def token = Jwts.parser().setSigningKey(key).parse(jwt) - - //noinspection GrEqualsBetweenInconvertibleTypes - assert token.header == [alg: alg.name()] - //noinspection GrEqualsBetweenInconvertibleTypes - assert token.body == claims - } - - static void testEC(SignatureAlgorithm alg, boolean verifyWithPrivateKey = false) { - - KeyPair pair = Keys.keyPairFor(alg) - PublicKey publicKey = pair.getPublic() - PrivateKey privateKey = pair.getPrivate() - - def claims = [iss: 'joe', exp: later(), 'http://example.com/is_root': true] - - String jwt = Jwts.builder().setClaims(claims).signWith(privateKey, alg).compact() - - def key = publicKey - if (verifyWithPrivateKey) { - key = privateKey - } - - def token = Jwts.parser().setSigningKey(key).parse(jwt) - - //noinspection GrEqualsBetweenInconvertibleTypes - assert token.header == [alg: alg.name()] - //noinspection GrEqualsBetweenInconvertibleTypes - assert token.body == claims - } -} - diff --git a/impl/src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy index 06b97c02f..90d7e3965 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy @@ -53,12 +53,12 @@ class JwtParserTest { @Test void testIsSignedWithNullArgument() { - assertFalse Jwts.parserBuilder().build().isSigned(null) + assertFalse Jwts.parser().build().isSigned(null) } @Test void testIsSignedWithJunkArgument() { - assertFalse Jwts.parserBuilder().build().isSigned('hello') + assertFalse Jwts.parser().build().isSigned('hello') } @Test @@ -69,7 +69,7 @@ class JwtParserTest { String bad = base64Url('{"alg":"none"}') + '.' + base64Url(junkPayload) + '.' try { - Jwts.parserBuilder().enableUnsecuredJws().build().parse(bad) + Jwts.parser().enableUnsecuredJws().build().parse(bad) fail() } catch (MalformedJwtException expected) { assertEquals 'Unable to read claims JSON: ' + junkPayload, expected.getMessage() @@ -90,7 +90,7 @@ class JwtParserTest { String bad = base64Url(header) + '.' + base64Url(payload) + '.' + base64Url(badSig) try { - Jwts.parserBuilder().setSigningKey(randomKey()).build().parse(bad) + Jwts.parser().setSigningKey(randomKey()).build().parse(bad) fail() } catch (SignatureException se) { assertEquals se.getMessage(), "Unsupported signature algorithm '$badAlgorithmName'".toString() @@ -109,7 +109,7 @@ class JwtParserTest { String bad = base64Url(header) + '.' + base64Url(payload) + '.' + base64Url(badSig) try { - Jwts.parserBuilder().setSigningKey(randomKey()).build().parse(bad) + Jwts.parser().setSigningKey(randomKey()).build().parse(bad) fail() } catch (SignatureException se) { assertEquals se.getMessage(), 'JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.' @@ -129,7 +129,7 @@ class JwtParserTest { String bad = base64Url(header) + '.' + base64Url(payload) + '.' + base64Url(badSig) try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(randomKey()).build().parse(bad) + Jwts.parser().enableUnsecuredJws().setSigningKey(randomKey()).build().parse(bad) fail() } catch (MalformedJwtException se) { assertEquals 'The JWS header references signature algorithm \'none\' yet the compact JWS string contains a signature. This is not permitted per https://tools.ietf.org/html/rfc7518#section-3.6.', se.getMessage() @@ -147,7 +147,7 @@ class JwtParserTest { def payload = '{"subject":"Joe"}' String unsecured = base64Url(header) + '.' + base64Url(payload) + '.' try { - Jwts.parserBuilder().build().parse(unsecured) + Jwts.parser().build().parse(unsecured) fail() } catch (UnsupportedJwtException expected) { String msg = DefaultJwtParser.UNSECURED_DISABLED_MSG_PREFIX + '{alg=none}' @@ -167,9 +167,9 @@ class JwtParserTest { //noinspection GrDeprecatedAPIUsage String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, base64Encodedkey).compact() - assertTrue Jwts.parserBuilder().build().isSigned(compact) + assertTrue Jwts.parser().build().isSigned(compact) - def jwt = Jwts.parserBuilder().setSigningKey(base64Encodedkey).build().parse(compact) + def jwt = Jwts.parser().setSigningKey(base64Encodedkey).build().parse(compact) assertEquals payload, new String(jwt.payload as byte[], StandardCharsets.UTF_8) } @@ -182,9 +182,9 @@ class JwtParserTest { String compact = Jwts.builder().setPayload(payload).signWith(key).compact() - assertTrue Jwts.parserBuilder().build().isSigned(compact) + assertTrue Jwts.parser().build().isSigned(compact) - def jwt = Jwts.parserBuilder().setSigningKey(key).build().parse(compact) + def jwt = Jwts.parser().setSigningKey(key).build().parse(compact) assertEquals payload, new String(jwt.payload as byte[], StandardCharsets.UTF_8) } @@ -193,16 +193,16 @@ class JwtParserTest { void testParseNullPayload() { SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256) String compact = Jwts.builder().signWith(key).compact() - assertTrue Jwts.parserBuilder().build().isSigned(compact) + assertTrue Jwts.parser().build().isSigned(compact) - def jwt = Jwts.parserBuilder().setSigningKey(key).build().parse(compact) + def jwt = Jwts.parser().setSigningKey(key).build().parse(compact) assertEquals '', new String(jwt.payload as byte[], StandardCharsets.UTF_8) } @Test void testParseNullPayloadWithoutKey() { String compact = Jwts.builder().compact() - def jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact) + def jwt = Jwts.parser().enableUnsecuredJws().build().parse(compact) assertEquals 'none', jwt.header.alg assertEquals '', new String(jwt.payload as byte[], StandardCharsets.UTF_8) } @@ -219,7 +219,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').setExpiration(exp).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().setClock(fixedClock).build().parse(compact) + Jwts.parser().enableUnsecuredJws().setClock(fixedClock).build().parse(compact) fail() } catch (ExpiredJwtException e) { // https://github.com/jwtk/jjwt/issues/107 (the Z designator at the end of the timestamp): @@ -237,7 +237,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').setNotBefore(nbf).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact) + Jwts.parser().enableUnsecuredJws().build().parse(compact) fail() } catch (PrematureJwtException e) { assertTrue e.getMessage().startsWith('JWT must not be accepted before ') @@ -254,7 +254,7 @@ class JwtParserTest { String subject = 'Joe' String compact = Jwts.builder().setSubject(subject).setExpiration(exp).compact() - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().setAllowedClockSkewSeconds(10).build().parse(compact) + Jwt jwt = Jwts.parser().enableUnsecuredJws().setAllowedClockSkewSeconds(10).build().parse(compact) assertEquals jwt.getPayload().getSubject(), subject } @@ -266,7 +266,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').setExpiration(exp).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().setAllowedClockSkewSeconds(1).build().parse(compact) + Jwts.parser().enableUnsecuredJws().setAllowedClockSkewSeconds(1).build().parse(compact) fail() } catch (ExpiredJwtException e) { assertTrue e.getMessage().startsWith('JWT expired at ') @@ -280,7 +280,7 @@ class JwtParserTest { String subject = 'Joe' String compact = Jwts.builder().setSubject(subject).setNotBefore(exp).compact() - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().setAllowedClockSkewSeconds(10).build().parse(compact) + Jwt jwt = Jwts.parser().enableUnsecuredJws().setAllowedClockSkewSeconds(10).build().parse(compact) assertEquals jwt.getPayload().getSubject(), subject } @@ -292,7 +292,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').setNotBefore(exp).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().setAllowedClockSkewSeconds(1).build().parse(compact) + Jwts.parser().enableUnsecuredJws().setAllowedClockSkewSeconds(1).build().parse(compact) fail() } catch (PrematureJwtException e) { assertTrue e.getMessage().startsWith('JWT must not be accepted before ') @@ -310,7 +310,7 @@ class JwtParserTest { String compact = Jwts.builder().setPayload(payload).compact() - def jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseContentJwt(compact) + def jwt = Jwts.parser().enableUnsecuredJws().build().parseContentJwt(compact) assertEquals payload, new String(jwt.payload, StandardCharsets.UTF_8) } @@ -321,7 +321,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').compact() try { - Jwts.parserBuilder().enableUnsecuredJws().build().parseContentJwt(compact) + Jwts.parser().enableUnsecuredJws().build().parseContentJwt(compact) fail() } catch (UnsupportedJwtException e) { assertEquals e.getMessage(), 'Unprotected Claims JWTs are not supported.' @@ -336,7 +336,7 @@ class JwtParserTest { String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, randomKey()).compact() try { - Jwts.parserBuilder().build().parseContentJwt(compact) + Jwts.parser().build().parseContentJwt(compact) fail() } catch (UnsupportedJwtException e) { assertEquals 'Cannot verify JWS signature: unable to locate signature verification key for JWS with header: {alg=HS256}', e.getMessage() @@ -350,7 +350,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').signWith(SignatureAlgorithm.HS256, key).compact() try { - Jwts.parserBuilder().setSigningKey(key).build().parseContentJws(compact) + Jwts.parser().setSigningKey(key).build().parseContentJws(compact) fail() } catch (UnsupportedJwtException e) { assertEquals 'Signed Claims JWTs are not supported.', e.getMessage() @@ -368,7 +368,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject(subject).compact() - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(compact) + Jwt jwt = Jwts.parser().enableUnsecuredJws().build().parseClaimsJwt(compact) assertEquals jwt.getPayload().getSubject(), subject } @@ -381,7 +381,7 @@ class JwtParserTest { String compact = Jwts.builder().setPayload(payload).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(compact) + Jwts.parser().enableUnsecuredJws().build().parseClaimsJwt(compact) fail() } catch (UnsupportedJwtException e) { assertEquals 'Unprotected content JWTs are not supported.', e.getMessage() @@ -396,7 +396,7 @@ class JwtParserTest { String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, randomKey()).compact() try { - Jwts.parserBuilder().build().parseClaimsJwt(compact) + Jwts.parser().build().parseClaimsJwt(compact) fail() } catch (UnsupportedJwtException e) { assertEquals 'Cannot verify JWS signature: unable to locate signature verification key for JWS with header: {alg=HS256}', e.getMessage() @@ -410,7 +410,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').signWith(SignatureAlgorithm.HS256, key).compact() try { - Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJwt(compact) + Jwts.parser().setSigningKey(key).build().parseClaimsJwt(compact) fail() } catch (UnsupportedJwtException e) { assertEquals 'Signed Claims JWTs are not supported.', e.getMessage() @@ -427,7 +427,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').setExpiration(exp).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(compact) + Jwts.parser().enableUnsecuredJws().build().parseClaimsJwt(compact) fail() } catch (ExpiredJwtException e) { assertTrue e.getMessage().startsWith('JWT expired at ') @@ -442,7 +442,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').setNotBefore(nbf).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(compact) + Jwts.parser().enableUnsecuredJws().build().parseClaimsJwt(compact) fail() } catch (PrematureJwtException e) { assertTrue e.getMessage().startsWith('JWT must not be accepted before ') @@ -462,7 +462,7 @@ class JwtParserTest { String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, key).compact() - def jwt = Jwts.parserBuilder(). + def jwt = Jwts.parser(). setSigningKey(key). build(). parseContentJws(compact) @@ -480,7 +480,7 @@ class JwtParserTest { String compact = Jwts.builder().setPayload(payload).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parseContentJws(compact) + Jwts.parser().enableUnsecuredJws().setSigningKey(key).build().parseContentJws(compact) fail() } catch (UnsupportedJwtException e) { assertEquals 'Unprotected content JWTs are not supported.', e.getMessage() @@ -497,7 +497,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject(subject).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parseContentJws(compact) + Jwts.parser().enableUnsecuredJws().setSigningKey(key).build().parseContentJws(compact) fail() } catch (UnsupportedJwtException e) { assertEquals 'Unprotected Claims JWTs are not supported.', e.getMessage() @@ -514,7 +514,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject(subject).signWith(SignatureAlgorithm.HS256, key).compact() try { - Jwts.parserBuilder().setSigningKey(key).build().parseContentJws(compact) + Jwts.parser().setSigningKey(key).build().parseContentJws(compact) fail() } catch (UnsupportedJwtException e) { assertEquals 'Signed Claims JWTs are not supported.', e.getMessage() @@ -534,7 +534,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject(sub).signWith(SignatureAlgorithm.HS256, key).compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(compact) + Jwt jwt = Jwts.parser().setSigningKey(key).build().parseClaimsJws(compact) assertEquals jwt.getPayload().getSubject(), sub } @@ -553,7 +553,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject(sub).signWith(SignatureAlgorithm.HS256, key).setExpiration(exp).compact() try { - Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJwt(compact) + Jwts.parser().setSigningKey(key).build().parseClaimsJwt(compact) fail() } catch (ExpiredJwtException e) { assertTrue e.getMessage().startsWith('JWT expired at ') @@ -574,7 +574,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject(sub).setNotBefore(nbf).signWith(SignatureAlgorithm.HS256, key).compact() try { - Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(compact) + Jwts.parser().setSigningKey(key).build().parseClaimsJws(compact) fail() } catch (PrematureJwtException e) { assertTrue e.getMessage().startsWith('JWT must not be accepted before ') @@ -593,7 +593,7 @@ class JwtParserTest { String compact = Jwts.builder().setPayload(payload).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parseClaimsJws(compact) + Jwts.parser().enableUnsecuredJws().setSigningKey(key).build().parseClaimsJws(compact) fail() } catch (UnsupportedJwtException e) { assertEquals 'Unprotected content JWTs are not supported.', e.getMessage() @@ -610,7 +610,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject(subject).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key). + Jwts.parser().enableUnsecuredJws().setSigningKey(key). build(). parseClaimsJws(compact) fail() @@ -629,7 +629,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject(subject).signWith(SignatureAlgorithm.HS256, key).compact() try { - Jwts.parserBuilder().setSigningKey(key).build().parseContentJws(compact) + Jwts.parser().setSigningKey(key).build().parseContentJws(compact) fail() } catch (UnsupportedJwtException e) { assertEquals 'Signed Claims JWTs are not supported.', e.getMessage() @@ -656,7 +656,7 @@ class JwtParserTest { } } - Jws jws = Jwts.parserBuilder().setSigningKeyResolver(signingKeyResolver).build().parseClaimsJws(compact) + Jws jws = Jwts.parser().setSigningKeyResolver(signingKeyResolver).build().parseClaimsJws(compact) assertEquals jws.getPayload().getSubject(), subject } @@ -678,7 +678,7 @@ class JwtParserTest { } try { - Jwts.parserBuilder().setSigningKeyResolver(signingKeyResolver).build().parseClaimsJws(compact) + Jwts.parser().setSigningKeyResolver(signingKeyResolver).build().parseClaimsJws(compact) fail() } catch (SignatureException se) { assertEquals 'JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.', se.getMessage() @@ -695,7 +695,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject(subject).signWith(SignatureAlgorithm.HS256, key).compact() try { - Jwts.parserBuilder().setSigningKeyResolver(null).build().parseClaimsJws(compact) + Jwts.parser().setSigningKeyResolver(null).build().parseClaimsJws(compact) fail() } catch (IllegalArgumentException iae) { assertEquals 'SigningKeyResolver cannot be null.', iae.getMessage() @@ -714,7 +714,7 @@ class JwtParserTest { def signingKeyResolver = new SigningKeyResolverAdapter() try { - Jwts.parserBuilder().setSigningKeyResolver(signingKeyResolver).build().parseClaimsJws(compact) + Jwts.parser().setSigningKeyResolver(signingKeyResolver).build().parseClaimsJws(compact) fail() } catch (UnsupportedJwtException ex) { assertEquals 'The specified SigningKeyResolver implementation does not support ' + @@ -742,7 +742,7 @@ class JwtParserTest { claim("long_big", bigLong). compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(compact) + Jwt jwt = Jwts.parser().setSigningKey(key).build().parseClaimsJws(compact) Claims claims = jwt.getPayload() @@ -773,7 +773,7 @@ class JwtParserTest { } } - def jws = Jwts.parserBuilder().setSigningKeyResolver(signingKeyResolver).build().parseContentJws(compact) + def jws = Jwts.parser().setSigningKeyResolver(signingKeyResolver).build().parseContentJws(compact) assertEquals inputPayload, new String(jws.payload, StandardCharsets.UTF_8) } @@ -795,7 +795,7 @@ class JwtParserTest { } try { - Jwts.parserBuilder().setSigningKeyResolver(signingKeyResolver).build().parseContentJws(compact) + Jwts.parser().setSigningKeyResolver(signingKeyResolver).build().parseContentJws(compact) fail() } catch (SignatureException se) { assertEquals 'JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.', se.getMessage() @@ -814,7 +814,7 @@ class JwtParserTest { def signingKeyResolver = new SigningKeyResolverAdapter() try { - Jwts.parserBuilder().setSigningKeyResolver(signingKeyResolver).build().parseContentJws(compact) + Jwts.parser().setSigningKeyResolver(signingKeyResolver).build().parseContentJws(compact) fail() } catch (UnsupportedJwtException ex) { assertEquals ex.getMessage(), 'The specified SigningKeyResolver implementation does not support content ' + @@ -834,7 +834,7 @@ class JwtParserTest { try { // expecting null claim name, but with value - Jwts.parserBuilder().setSigningKey(key).require(null, expectedClaimValue).build().parseClaimsJws(compact) + Jwts.parser().setSigningKey(key).require(null, expectedClaimValue).build().parseClaimsJws(compact) fail() } catch (IllegalArgumentException e) { assertEquals( @@ -857,7 +857,7 @@ class JwtParserTest { try { // expecting null claim name, but with value - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). require("", expectedClaimValue). build(). parseClaimsJws(compact) @@ -881,7 +881,7 @@ class JwtParserTest { try { // expecting claim name, but with null value - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). require(expectedClaimName, null). build(). parseClaimsJws(compact) @@ -905,7 +905,7 @@ class JwtParserTest { claim(expectedClaimName, expectedClaimValue). compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). require(expectedClaimName, expectedClaimValue). build(). parseClaimsJws(compact) @@ -927,7 +927,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). require(goodClaimName, goodClaimValue). build(). parseClaimsJws(compact) @@ -952,7 +952,7 @@ class JwtParserTest { compact() try { - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). require(claimName, claimValue). build(). parseClaimsJws(compact) @@ -976,7 +976,7 @@ class JwtParserTest { setIssuedAt(issuedAt). compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). requireIssuedAt(issuedAt). build(). parseClaimsJws(compact) @@ -995,7 +995,7 @@ class JwtParserTest { setIssuedAt(badIssuedAt). compact() - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireIssuedAt(goodIssuedAt). build(). parseClaimsJws(compact) @@ -1011,7 +1011,7 @@ class JwtParserTest { setSubject("Dummy"). compact() - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireIssuedAt(issuedAt). build(). parseClaimsJws(compact) @@ -1027,7 +1027,7 @@ class JwtParserTest { setIssuer(issuer). compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). requireIssuer(issuer). build(). parseClaimsJws(compact) @@ -1047,7 +1047,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireIssuer(goodIssuer). build(). parseClaimsJws(compact) @@ -1071,7 +1071,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireIssuer(issuer). build(). parseClaimsJws(compact) @@ -1094,7 +1094,7 @@ class JwtParserTest { setAudience(audience). compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). requireAudience(audience). build(). parseClaimsJws(compact) @@ -1114,7 +1114,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireAudience(goodAudience). build(). parseClaimsJws(compact) @@ -1138,7 +1138,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireAudience(audience). build(). parseClaimsJws(compact) @@ -1161,7 +1161,7 @@ class JwtParserTest { setSubject(subject). compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). requireSubject(subject). build(). parseClaimsJws(compact) @@ -1181,7 +1181,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireSubject(goodSubject). build(). parseClaimsJws(compact) @@ -1205,7 +1205,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireSubject(subject). build(). parseClaimsJws(compact) @@ -1228,7 +1228,7 @@ class JwtParserTest { setId(id). compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). requireId(id). build(). parseClaimsJws(compact) @@ -1248,7 +1248,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireId(goodId). build(). parseClaimsJws(compact) @@ -1272,7 +1272,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireId(id). build(). parseClaimsJws(compact) @@ -1296,7 +1296,7 @@ class JwtParserTest { setExpiration(expiration). compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). requireExpiration(expiration). build(). parseClaimsJws(compact) @@ -1315,7 +1315,7 @@ class JwtParserTest { setExpiration(badExpiration). compact() - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireExpiration(goodExpiration). build(). parseClaimsJws(compact) @@ -1331,7 +1331,7 @@ class JwtParserTest { setSubject("Dummy"). compact() - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireExpiration(expiration). build(). parseClaimsJws(compact) @@ -1348,7 +1348,7 @@ class JwtParserTest { setNotBefore(notBefore). compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). requireNotBefore(notBefore). build(). parseClaimsJws(compact) @@ -1367,7 +1367,7 @@ class JwtParserTest { setNotBefore(badNotBefore). compact() - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireNotBefore(goodNotBefore). build(). parseClaimsJws(compact) @@ -1383,7 +1383,7 @@ class JwtParserTest { setSubject("Dummy"). compact() - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). requireNotBefore(notBefore). build(). parseClaimsJws(compact) @@ -1400,7 +1400,7 @@ class JwtParserTest { claim("aDate", aDate). compact() - Jwt jwt = Jwts.parserBuilder().setSigningKey(key). + Jwt jwt = Jwts.parser().setSigningKey(key). require("aDate", aDate). build(). parseClaimsJws(compact) @@ -1422,7 +1422,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). require("aDate", goodDate). build(). parseClaimsJws(compact) @@ -1447,7 +1447,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). require("aDate", goodDate). build(). parseClaimsJws(compact) @@ -1471,7 +1471,7 @@ class JwtParserTest { compact() try { - Jwts.parserBuilder().setSigningKey(key). + Jwts.parser().setSigningKey(key). require("aDate", aDate). build(). parseClaimsJws(compact) @@ -1492,12 +1492,12 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').setExpiration(expiry).compact() - Jwts.parserBuilder().enableUnsecuredJws().setClock(new FixedClock(beforeExpiry)).build().parse(compact) + Jwts.parser().enableUnsecuredJws().setClock(new FixedClock(beforeExpiry)).build().parse(compact) } @Test void testParseClockManipulationWithNullClock() { - JwtParserBuilder parser = Jwts.parserBuilder(); + JwtParserBuilder parser = Jwts.parser(); try { parser.setClock(null) fail() @@ -1512,7 +1512,7 @@ class JwtParserTest { String compact = Jwts.builder().setSubject('Joe').setExpiration(expiry).compact() try { - Jwts.parserBuilder().enableUnsecuredJws().setClock(new DefaultClock()).build().parse(compact) + Jwts.parser().enableUnsecuredJws().setClock(new DefaultClock()).build().parse(compact) fail() } catch (ExpiredJwtException e) { assertTrue e.getMessage().startsWith('JWT expired at ') @@ -1533,7 +1533,7 @@ class JwtParserTest { String bad = base64Url(header) + '.' + base64Url(payload) + '.' + base64Url(badSig) + '.' + base64Url(bogus) try { - Jwts.parserBuilder().setSigningKey(randomKey()).build().parse(bad) + Jwts.parser().setSigningKey(randomKey()).build().parse(bad) fail() } catch (MalformedJwtException se) { String expected = JwtTokenizer.DELIM_ERR_MSG_PREFIX + '3' @@ -1549,7 +1549,7 @@ class JwtParserTest { String jwtStr = '.' + base64Url(payload) + '.' try { - Jwts.parserBuilder().build().parse(jwtStr) + Jwts.parser().build().parse(jwtStr) fail() } catch (MalformedJwtException e) { assertEquals 'Compact JWT strings MUST always have a Base64Url protected header per https://tools.ietf.org/html/rfc7519#section-7.2 (steps 2-4).', e.getMessage() @@ -1566,7 +1566,7 @@ class JwtParserTest { String jwtStr = '.' + base64Url(payload) + '.' + base64Url(sig) try { - Jwts.parserBuilder().build().parse(jwtStr) + Jwts.parser().build().parse(jwtStr) fail() } catch (MalformedJwtException se) { assertEquals 'Compact JWT strings MUST always have a Base64Url protected header per https://tools.ietf.org/html/rfc7519#section-7.2 (steps 2-4).', se.message @@ -1585,7 +1585,7 @@ class JwtParserTest { String jwtStr = base64Url(header) + '.' + base64Url(payload) + '.' + base64Url(sig) try { - Jwts.parserBuilder().enableUnsecuredJws().build().parse(jwtStr) + Jwts.parser().enableUnsecuredJws().build().parse(jwtStr) fail() } catch (MalformedJwtException se) { assertEquals 'The JWS header references signature algorithm \'none\' yet the compact JWS string contains a signature. This is not permitted per https://tools.ietf.org/html/rfc7518#section-3.6.', se.message diff --git a/impl/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy index 54045f4b3..c4dee7712 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy @@ -118,7 +118,7 @@ class JwtsTest { def encodedClaims = base64Url(claimsString) def compact = encodedHeader + '.' + encodedClaims + '.AAD=' try { - Jwts.parserBuilder().build().parseClaimsJws(compact) + Jwts.parser().build().parseClaimsJws(compact) fail() } catch (MalformedJwtException e) { String expected = 'Invalid protected header: Invalid JWS header \'jku\' (JWK Set URL) value: 42. ' + @@ -141,7 +141,7 @@ class JwtsTest { def sig = Encoders.BASE64URL.encode(result) def compact = "$h.$c.$sig" as String try { - Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(compact) + Jwts.parser().setSigningKey(key).build().parseClaimsJws(compact) fail() } catch (MalformedJwtException e) { String expected = 'Invalid claims: Invalid JWT Claim \'exp\' (Expiration Time) value: -42-. ' + @@ -166,7 +166,7 @@ class JwtsTest { String s = 'Hello JJWT' String cty = 'text/plain' String compact = Jwts.builder().setContent(s.getBytes(StandardCharsets.UTF_8), cty).compact() - def jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseContentJwt(compact) + def jwt = Jwts.parser().enableUnsecuredJws().build().parseContentJwt(compact) assertEquals cty, jwt.header.getContentType() assertEquals s, new String(jwt.payload, StandardCharsets.UTF_8) } @@ -177,7 +177,7 @@ class JwtsTest { String subtype = 'foo' String cty = "application/$subtype" String compact = Jwts.builder().setContent(s.getBytes(StandardCharsets.UTF_8), cty).compact() - def jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseContentJwt(compact) + def jwt = Jwts.parser().enableUnsecuredJws().build().parseContentJwt(compact) assertEquals subtype, jwt.header.getContentType() // assert that the compact form was used assertEquals s, new String(jwt.payload, StandardCharsets.UTF_8) } @@ -188,7 +188,7 @@ class JwtsTest { String subtype = 'foo' String cty = "application/$subtype;part=1/2" String compact = Jwts.builder().setContent(s.getBytes(StandardCharsets.UTF_8), cty).compact() - def jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseContentJwt(compact) + def jwt = Jwts.parser().enableUnsecuredJws().build().parseContentJwt(compact) assertEquals cty, jwt.header.getContentType() // two slashes, can't compact assertEquals s, new String(jwt.payload, StandardCharsets.UTF_8) } @@ -200,7 +200,7 @@ class JwtsTest { String jwt = Jwts.builder().setClaims(claims).compact() - def token = Jwts.parserBuilder().enableUnsecuredJws().build().parse(jwt) + def token = Jwts.parser().enableUnsecuredJws().build().parse(jwt) //noinspection GrEqualsBetweenInconvertibleTypes assert token.payload == claims @@ -208,17 +208,17 @@ class JwtsTest { @Test(expected = IllegalArgumentException) void testParseNull() { - Jwts.parserBuilder().build().parse(null) + Jwts.parser().build().parse(null) } @Test(expected = IllegalArgumentException) void testParseEmptyString() { - Jwts.parserBuilder().build().parse('') + Jwts.parser().build().parse('') } @Test(expected = IllegalArgumentException) void testParseWhitespaceString() { - Jwts.parserBuilder().build().parse(' ') + Jwts.parser().build().parse(' ') } @Test @@ -230,7 +230,7 @@ class JwtsTest { String claims = Encoders.BASE64URL.encode(claimsJson.getBytes(StandardCharsets.UTF_8)) String compact = header + '.' + claims + '.' - def jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(compact) + def jwt = Jwts.parser().enableUnsecuredJws().build().parseClaimsJwt(compact) assertEquals 'none', jwt.header.getAlgorithm() assertEquals 'joe', jwt.payload.getSubject() } @@ -238,7 +238,7 @@ class JwtsTest { @Test void testParseWithNoPeriods() { try { - Jwts.parserBuilder().build().parse('foo') + Jwts.parser().build().parse('foo') fail() } catch (MalformedJwtException e) { //noinspection GroovyAccessibility @@ -250,7 +250,7 @@ class JwtsTest { @Test void testParseWithOnePeriodOnly() { try { - Jwts.parserBuilder().build().parse('.') + Jwts.parser().build().parse('.') fail() } catch (MalformedJwtException e) { //noinspection GroovyAccessibility @@ -262,7 +262,7 @@ class JwtsTest { @Test void testParseWithTwoPeriodsOnly() { try { - Jwts.parserBuilder().build().parse('..') + Jwts.parser().build().parse('..') fail() } catch (MalformedJwtException e) { String msg = 'Compact JWT strings MUST always have a Base64Url protected header per ' + @@ -274,14 +274,14 @@ class JwtsTest { @Test void testParseWithHeaderOnly() { String unsecuredJwt = base64Url("{\"alg\":\"none\"}") + ".." - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parse(unsecuredJwt) + Jwt jwt = Jwts.parser().enableUnsecuredJws().build().parse(unsecuredJwt) assertEquals "none", jwt.getHeader().get("alg") } @Test void testParseWithSignatureOnly() { try { - Jwts.parserBuilder().build().parse('..bar') + Jwts.parser().build().parse('..bar') fail() } catch (MalformedJwtException e) { assertEquals 'Compact JWT strings MUST always have a Base64Url protected header per https://tools.ietf.org/html/rfc7519#section-7.2 (steps 2-4).', e.message @@ -295,7 +295,7 @@ class JwtsTest { int i = compact.lastIndexOf('.') String missingSig = compact.substring(0, i + 1) try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parseClaimsJws(missingSig) + Jwts.parser().enableUnsecuredJws().setSigningKey(key).build().parseClaimsJws(missingSig) fail() } catch (MalformedJwtException expected) { String s = String.format(DefaultJwtParser.MISSING_JWS_DIGEST_MSG_FMT, 'HS256') @@ -315,7 +315,7 @@ class JwtsTest { @Test void testConvenienceIssuer() { String compact = Jwts.builder().setIssuer("Me").compact() - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + Claims claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertEquals 'Me', claims.getIssuer() compact = Jwts.builder().setSubject("Joe") @@ -323,14 +323,14 @@ class JwtsTest { .setIssuer(null) //null should remove it .compact() - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertNull claims.getIssuer() } @Test void testConvenienceSubject() { String compact = Jwts.builder().setSubject("Joe").compact() - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + Claims claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertEquals 'Joe', claims.getSubject() compact = Jwts.builder().setIssuer("Me") @@ -338,14 +338,14 @@ class JwtsTest { .setSubject(null) //null should remove it .compact() - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertNull claims.getSubject() } @Test void testConvenienceAudience() { String compact = Jwts.builder().setAudience("You").compact() - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + Claims claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertEquals 'You', claims.getAudience() compact = Jwts.builder().setIssuer("Me") @@ -353,7 +353,7 @@ class JwtsTest { .setAudience(null) //null should remove it .compact() - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertNull claims.getAudience() } @@ -361,7 +361,7 @@ class JwtsTest { void testConvenienceExpiration() { Date then = laterDate(10000) String compact = Jwts.builder().setExpiration(then).compact() - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + Claims claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims def claimedDate = claims.getExpiration() assertEquals then, claimedDate @@ -370,7 +370,7 @@ class JwtsTest { .setExpiration(null) //null should remove it .compact() - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertNull claims.getExpiration() } @@ -378,7 +378,7 @@ class JwtsTest { void testConvenienceNotBefore() { Date now = now() //jwt exp only supports *seconds* since epoch: String compact = Jwts.builder().setNotBefore(now).compact() - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + Claims claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims def claimedDate = claims.getNotBefore() assertEquals now, claimedDate @@ -387,7 +387,7 @@ class JwtsTest { .setNotBefore(null) //null should remove it .compact() - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertNull claims.getNotBefore() } @@ -395,7 +395,7 @@ class JwtsTest { void testConvenienceIssuedAt() { Date now = now() //jwt exp only supports *seconds* since epoch: String compact = Jwts.builder().setIssuedAt(now).compact() - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + Claims claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims def claimedDate = claims.getIssuedAt() assertEquals now, claimedDate @@ -404,7 +404,7 @@ class JwtsTest { .setIssuedAt(null) //null should remove it .compact() - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertNull claims.getIssuedAt() } @@ -412,7 +412,7 @@ class JwtsTest { void testConvenienceId() { String id = UUID.randomUUID().toString() String compact = Jwts.builder().setId(id).compact() - Claims claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + Claims claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertEquals id, claims.getId() compact = Jwts.builder().setIssuer("Me") @@ -420,7 +420,7 @@ class JwtsTest { .setId(null) //null should remove it .compact() - claims = Jwts.parserBuilder().enableUnsecuredJws().build().parse(compact).payload as Claims + claims = Jwts.parser().enableUnsecuredJws().build().parse(compact).payload as Claims assertNull claims.getId() } @@ -435,7 +435,7 @@ class JwtsTest { String compact = Jwts.builder().setId(id).setAudience("an audience").signWith(key, alg) .claim("state", "hello this is an amazing jwt").compact() - def jws = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(compact) + def jws = Jwts.parser().setSigningKey(key).build().parseClaimsJws(compact) Claims claims = jws.payload @@ -457,7 +457,7 @@ class JwtsTest { String compact = Jwts.builder().setId(id).setAudience("an audience").signWith(key, alg) .claim("state", "hello this is an amazing jwt").compressWith(Jwts.ZIP.DEF).compact() - def jws = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(compact) + def jws = Jwts.parser().setSigningKey(key).build().parseClaimsJws(compact) Claims claims = jws.payload @@ -479,7 +479,7 @@ class JwtsTest { String compact = Jwts.builder().setId(id).setAudience("an audience").signWith(key, alg) .claim("state", "hello this is an amazing jwt").compressWith(Jwts.ZIP.GZIP).compact() - def jws = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(compact) + def jws = Jwts.parser().setSigningKey(key).build().parseClaimsJws(compact) Claims claims = jws.payload @@ -506,7 +506,7 @@ class JwtsTest { } }).compact() - def jws = Jwts.parserBuilder().setSigningKey(key).setCompressionCodecResolver(new CompressionCodecResolver() { + def jws = Jwts.parser().setSigningKey(key).setCompressionCodecResolver(new CompressionCodecResolver() { @Override CompressionCodec resolveCompressionCodec(Header header) throws CompressionException { String algorithm = header.getCompressionAlgorithm() @@ -545,7 +545,7 @@ class JwtsTest { } }).compact() - Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(compact) + Jwts.parser().setSigningKey(key).build().parseClaimsJws(compact) } @Test @@ -559,7 +559,7 @@ class JwtsTest { String compact = Jwts.builder().setPayload(payload).signWith(key, alg) .compressWith(Jwts.ZIP.DEF).compact() - def jws = Jwts.parserBuilder().setSigningKey(key).build().parseContentJws(compact) + def jws = Jwts.parser().setSigningKey(key).build().parseContentJws(compact) assertEquals "DEF", jws.header.getCompressionAlgorithm() @@ -678,7 +678,7 @@ class JwtsTest { String jws = Jwts.builder().setSubject("Foo").signWith(key, alg).compact() - Jwts.parserBuilder().setSigningKey(weakKey).build().parseClaimsJws(jws) + Jwts.parser().setSigningKey(weakKey).build().parseClaimsJws(jws) fail('parseClaimsJws must fail for weak keys') } @@ -722,7 +722,7 @@ class JwtsTest { void testParserWithMismatchedEllipticCurveKeyAndAlgorithm() { def pair = TestKeys.ES256.pair def jws = Jwts.builder().setSubject('foo').signWith(pair.private).compact() - def parser = Jwts.parserBuilder().setSigningKey(TestKeys.ES384.pair.public).build() + def parser = Jwts.parser().setSigningKey(TestKeys.ES384.pair.public).build() try { parser.parseClaimsJws(jws) } catch (UnsupportedJwtException expected) { @@ -745,7 +745,7 @@ class JwtsTest { def invalidEncodedSignature = "_____wAAAAD__________7zm-q2nF56E87nKwvxjJVH_____AAAAAP__________vOb6racXnoTzucrC_GMlUQ" String jws = withoutSignature + '.' + invalidEncodedSignature def keypair = Jwts.SIG.ES256.keyPairBuilder().build() - Jwts.parserBuilder().setSigningKey(keypair.public).build().parseClaimsJws(jws) + Jwts.parser().setSigningKey(keypair.public).build().parseClaimsJws(jws) } //Asserts correct/expected behavior discussed in https://github.com/jwtk/jjwt/issues/20 @@ -759,7 +759,7 @@ class JwtsTest { String notSigned = Jwts.builder().setSubject("Foo").compact() try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parseClaimsJws(notSigned) + Jwts.parser().enableUnsecuredJws().setSigningKey(key).build().parseClaimsJws(notSigned) fail('parseClaimsJws must fail for unsigned JWTs') } catch (UnsupportedJwtException expected) { assertEquals 'Unprotected Claims JWTs are not supported.', expected.message @@ -775,7 +775,7 @@ class JwtsTest { def c = base64Url('{"sub":"joe"}') def compact = h + '.ecek.iv.' + c + '.tag' try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (MalformedJwtException e) { assertEquals DefaultJwtParser.MISSING_JWE_ALG_MSG, e.getMessage() @@ -791,7 +791,7 @@ class JwtsTest { def c = base64Url('{"sub":"joe"}') def compact = h + '.ecek.iv.' + c + '.tag' try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (MalformedJwtException e) { assertEquals DefaultJwtParser.MISSING_JWE_ALG_MSG, e.getMessage() @@ -807,7 +807,7 @@ class JwtsTest { def c = base64Url('{"sub":"joe"}') def compact = h + '.ecek.iv.' + c + '.tag' try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (MalformedJwtException e) { assertEquals DefaultJwtParser.MISSING_JWE_ALG_MSG, e.getMessage() @@ -823,7 +823,7 @@ class JwtsTest { def c = base64Url('{"sub":"joe"}') def compact = h + '.ecek.iv.' + c + '.tag' try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (MalformedJwtException e) { assertEquals DefaultJwtParser.JWE_NONE_MSG, e.getMessage() @@ -839,7 +839,7 @@ class JwtsTest { def c = base64Url('{"sub":"joe"}') def compact = h + '.ecek.iv.' + c + '.' try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (MalformedJwtException e) { String expected = String.format(DefaultJwtParser.MISSING_JWE_DIGEST_MSG_FMT, 'dir') @@ -858,7 +858,7 @@ class JwtsTest { def tag = '&' def compact = h + '.IA==.IA==.' + c + '.' + tag try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (MalformedJwtException e) { String expected = 'Compact JWE strings must always contain an AAD Authentication Tag.' @@ -874,7 +874,7 @@ class JwtsTest { def h = base64Url('{"alg":"dir","enc":"A128GCM"}') def compact = h + '.ecek.iv..tag' try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (MalformedJwtException e) { String expected = 'Compact JWE strings MUST always contain a payload (ciphertext).' @@ -893,7 +893,7 @@ class JwtsTest { def encodedKey = '&' def compact = h + '.' + encodedKey + '.iv.' + c + '.tag' try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (MalformedJwtException e) { String expected = 'Compact JWE string represents an encrypted key, but the key is empty.' @@ -910,7 +910,7 @@ class JwtsTest { def c = base64Url('{"sub":"joe"}') def compact = h + '.IA==..' + c + '.tag' try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (MalformedJwtException e) { String expected = 'Compact JWE strings must always contain an Initialization Vector.' @@ -930,7 +930,7 @@ class JwtsTest { def tag = 'IA==' def compact = "$h.$ekey.$iv.$c.$tag" as String try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (MalformedJwtException e) { assertEquals DefaultJwtParser.MISSING_ENC_MSG, e.getMessage() @@ -949,7 +949,7 @@ class JwtsTest { def tag = 'IA==' def compact = "$h.$ekey.$iv.$c.$tag" as String try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (UnsupportedJwtException e) { String expected = "Unrecognized JWE 'enc' (Encryption Algorithm) header value: foo" @@ -969,7 +969,7 @@ class JwtsTest { def tag = 'IA==' def compact = "$h.$ekey.$iv.$c.$tag" as String try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (UnsupportedJwtException e) { String expected = "Unrecognized JWE 'alg' (Algorithm) header value: bar" @@ -987,7 +987,7 @@ class JwtsTest { def sig = 'IA==' def compact = "$h.$c.$sig" as String try { - Jwts.parserBuilder().build().parseClaimsJws(compact) + Jwts.parser().build().parseClaimsJws(compact) fail() } catch (io.jsonwebtoken.security.SignatureException e) { String expected = "Unsupported signature algorithm 'bar'" @@ -1007,7 +1007,7 @@ class JwtsTest { def tag = 'IA==' def compact = "$h.$ekey.$iv.$c.$tag" as String try { - Jwts.parserBuilder().build().parseClaimsJwe(compact) + Jwts.parser().build().parseClaimsJwe(compact) fail() } catch (UnsupportedJwtException e) { String expected = "Cannot decrypt JWE payload: unable to locate key for JWE with header: {alg=dir, enc=A128GCM}" @@ -1052,7 +1052,7 @@ class JwtsTest { def jws = Jwts.builder().setSubject("joe").signWith(key, alg).compact() - assertEquals 'joe', Jwts.parserBuilder() + assertEquals 'joe', Jwts.parser() .addSignatureAlgorithms([alg]) .setSigningKey(key) .build() @@ -1096,7 +1096,7 @@ class JwtsTest { def jwe = Jwts.builder().setSubject("joe").encryptWith(key, encAlg).compact() - assertEquals 'joe', Jwts.parserBuilder() + assertEquals 'joe', Jwts.parser() .addEncryptionAlgorithms([encAlg]) .decryptWith(key) .build() @@ -1134,7 +1134,7 @@ class JwtsTest { } try { - Jwts.parserBuilder() + Jwts.parser() .setKeyLocator(new ConstantKeyLocator(TestKeys.HS256, TestKeys.A128GCM)) .addKeyAlgorithms([badKeyAlg]) // <-- add bad alg here .build() @@ -1154,7 +1154,7 @@ class JwtsTest { void testParseRequiredInt() { def key = TestKeys.HS256 def jws = Jwts.builder().signWith(key).claim("foo", 42).compact() - Jwts.parserBuilder().setSigningKey(key) + Jwts.parser().setSigningKey(key) .require("foo", 42L) //require a long, but jws contains int, should still work .build().parseClaimsJws(jws) } @@ -1178,14 +1178,14 @@ class JwtsTest { String forged = Jwts.builder().setSubject("Not Joe").compact() //assert that our forged header has a 'NONE' algorithm: - assertEquals 'none', Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(forged).getHeader().get('alg') + assertEquals 'none', Jwts.parser().enableUnsecuredJws().build().parseClaimsJwt(forged).getHeader().get('alg') //now let's forge it by appending the signature the server expects: forged += signature //now assert that, when the server tries to parse the forged token, parsing fails: try { - Jwts.parserBuilder().enableUnsecuredJws().setSigningKey(key).build().parse(forged) + Jwts.parser().enableUnsecuredJws().setSigningKey(key).build().parse(forged) fail("Parsing must fail for a forged token.") } catch (MalformedJwtException expected) { assertEquals 'The JWS header references signature algorithm \'none\' yet the compact JWS string contains a signature. This is not permitted per https://tools.ietf.org/html/rfc7518#section-3.6.', expected.message @@ -1217,7 +1217,7 @@ class JwtsTest { // Assert that the server (that should always use the private key) does not recognized the forged token: try { - Jwts.parserBuilder().setSigningKey(privateKey).build().parse(forged) + Jwts.parser().setSigningKey(privateKey).build().parse(forged) fail("Forged token must not be successfully parsed.") } catch (UnsupportedJwtException expected) { assertTrue expected.getMessage().startsWith('The parsed JWT indicates it was signed with the') @@ -1249,7 +1249,7 @@ class JwtsTest { // Assert that the parser does not recognized the forged token: try { - Jwts.parserBuilder().setSigningKey(publicKey).build().parse(forged) + Jwts.parser().setSigningKey(publicKey).build().parse(forged) fail("Forged token must not be successfully parsed.") } catch (UnsupportedJwtException expected) { assertTrue expected.getMessage().startsWith('The parsed JWT indicates it was signed with the') @@ -1281,7 +1281,7 @@ class JwtsTest { // Assert that the parser does not recognized the forged token: try { - Jwts.parserBuilder().setSigningKey(publicKey).build().parse(forged) + Jwts.parser().setSigningKey(publicKey).build().parse(forged) fail("Forged token must not be successfully parsed.") } catch (UnsupportedJwtException expected) { assertTrue expected.getMessage().startsWith('The parsed JWT indicates it was signed with the') @@ -1310,7 +1310,7 @@ class JwtsTest { .compact() //decrypt: - def jwt = Jwts.parserBuilder() + def jwt = Jwts.parser() .decryptWith(key) .build() .parseClaimsJwe(jwe) @@ -1338,7 +1338,7 @@ class JwtsTest { .compact() //decompress and decrypt: - def jwt = Jwts.parserBuilder() + def jwt = Jwts.parser() .decryptWith(key) .build() .parseClaimsJwe(jwe) @@ -1367,7 +1367,7 @@ class JwtsTest { .compact() //decrypt: - def jwt = Jwts.parserBuilder() + def jwt = Jwts.parser() .decryptWith(key) .build() .parseClaimsJwe(jwe) @@ -1388,7 +1388,7 @@ class JwtsTest { .compact() //decrypt: - def jwt = Jwts.parserBuilder() + def jwt = Jwts.parser() .decryptWith(key) .build() .parseClaimsJwe(jwe) @@ -1421,7 +1421,7 @@ class JwtsTest { .compact() //decrypt: - def jwt = Jwts.parserBuilder() + def jwt = Jwts.parser() .decryptWith(privKey) .build() .parseClaimsJwe(jwe) @@ -1456,7 +1456,7 @@ class JwtsTest { .compact() //decrypt: - def jwt = Jwts.parserBuilder() + def jwt = Jwts.parser() .decryptWith(privKey) .build() .parseClaimsJwe(jwe) @@ -1560,7 +1560,7 @@ class JwtsTest { } static Jwe decrypt(String jwe, PrivateKey key) { - return Jwts.parserBuilder().decryptWith(key).build().parseClaimsJwe(jwe) + return Jwts.parser().decryptWith(key).build().parseClaimsJwe(jwe) } static void testRsa(io.jsonwebtoken.security.SignatureAlgorithm alg, boolean verifyWithPrivateKey = false) { @@ -1578,7 +1578,7 @@ class JwtsTest { key = privateKey } - def token = Jwts.parserBuilder().verifyWith(key).build().parse(jwt) + def token = Jwts.parser().verifyWith(key).build().parse(jwt) assertEquals([alg: alg.getId()], token.header) assertEquals(claims, token.payload) @@ -1593,7 +1593,7 @@ class JwtsTest { String jwt = Jwts.builder().setClaims(claims).signWith(key, alg).compact() - def token = Jwts.parserBuilder().verifyWith(key).build().parse(jwt) + def token = Jwts.parser().verifyWith(key).build().parse(jwt) assertEquals([alg: alg.getId()], token.header) assertEquals(claims, token.payload) @@ -1614,7 +1614,7 @@ class JwtsTest { key = privateKey } - def token = Jwts.parserBuilder().verifyWith(key).build().parse(jwt) + def token = Jwts.parser().verifyWith(key).build().parse(jwt) assertEquals([alg: alg.getId()], token.header) assertEquals(claims, token.payload) diff --git a/impl/src/test/groovy/io/jsonwebtoken/RsaSigningKeyResolverAdapterTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/RsaSigningKeyResolverAdapterTest.groovy index 8f653c426..7abedf882 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/RsaSigningKeyResolverAdapterTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/RsaSigningKeyResolverAdapterTest.groovy @@ -32,7 +32,7 @@ class RsaSigningKeyResolverAdapterTest { def compact = Jwts.builder().claim('foo', 'bar').signWith(pair.private, alg).compact() - Jws jws = Jwts.parserBuilder().setSigningKey(pair.public).build().parseClaimsJws(compact) + Jws jws = Jwts.parser().setSigningKey(pair.public).build().parseClaimsJws(compact) try { new SigningKeyResolverAdapter().resolveSigningKey(jws.header, jws.payload) diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJweTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJweTest.groovy index 88da99e8d..67a3f2290 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJweTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJweTest.groovy @@ -30,7 +30,7 @@ class DefaultJweTest { def alg = Jwts.ENC.A128CBC_HS256 as AeadAlgorithm def key = alg.keyBuilder().build() String compact = Jwts.builder().claim('foo', 'bar').encryptWith(key, alg).compact() - def jwe = Jwts.parserBuilder().decryptWith(key).build().parseClaimsJwe(compact) + def jwe = Jwts.parser().decryptWith(key).build().parseClaimsJwe(compact) String encodedIv = Encoders.BASE64URL.encode(jwe.initializationVector) String encodedTag = Encoders.BASE64URL.encode(jwe.digest) String expected = "header={alg=dir, enc=A128CBC-HS256},payload={foo=bar},tag=$encodedTag,iv=$encodedIv" @@ -42,7 +42,7 @@ class DefaultJweTest { def alg = Jwts.ENC.A128CBC_HS256 as AeadAlgorithm def key = alg.keyBuilder().build() String compact = Jwts.builder().claim('foo', 'bar').encryptWith(key, alg).compact() - def parser = Jwts.parserBuilder().decryptWith(key).build() + def parser = Jwts.parser().decryptWith(key).build() def jwe1 = parser.parseClaimsJwe(compact) def jwe2 = parser.parseClaimsJwe(compact) assertNotEquals jwe1, 'hello' as String diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwsTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwsTest.groovy index 0cfae6bab..b2393c5f3 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwsTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwsTest.groovy @@ -40,7 +40,7 @@ class DefaultJwsTest { String compact = Jwts.builder().claim('foo', 'bar').signWith(key, alg).compact() int i = compact.lastIndexOf('.') String signature = compact.substring(i + 1) - def jws = Jwts.parserBuilder().verifyWith(key).build().parseClaimsJws(compact) + def jws = Jwts.parser().verifyWith(key).build().parseClaimsJws(compact) assertEquals 'header={alg=HS256},payload={foo=bar},signature=' + signature, jws.toString() } @@ -49,7 +49,7 @@ class DefaultJwsTest { def alg = Jwts.SIG.HS256 def key = alg.keyBuilder().build() String compact = Jwts.builder().claim('foo', 'bar').signWith(key, alg).compact() - def parser = Jwts.parserBuilder().verifyWith(key).build() + def parser = Jwts.parser().verifyWith(key).build() def jws1 = parser.parseClaimsJws(compact) def jws2 = parser.parseClaimsJws(compact) assertNotEquals jws1, 'hello' as String diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtBuilderTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtBuilderTest.groovy index 64e10077d..850eadb27 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtBuilderTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtBuilderTest.groovy @@ -444,7 +444,7 @@ class DefaultJwtBuilderTest { .claim('foo', 'bar') .compact() - assertEquals 'bar', Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(jws).getPayload().get('foo') + assertEquals 'bar', Jwts.parser().setSigningKey(key).build().parseClaimsJws(jws).getPayload().get('foo') } @Test @@ -476,7 +476,7 @@ class DefaultJwtBuilderTest { def enc = Jwts.ENC.A128GCM def key = enc.keyBuilder().build() def jwe = builder.setPayload("me").encryptWith(key, enc).compact() - def jwt = Jwts.parserBuilder().decryptWith(key).build().parseContentJwe(jwe) + def jwt = Jwts.parser().decryptWith(key).build().parseContentJwe(jwe) assertEquals 'me', new String(jwt.getPayload(), StandardCharsets.UTF_8) } @@ -485,7 +485,7 @@ class DefaultJwtBuilderTest { def enc = Jwts.ENC.A128GCM def key = enc.keyBuilder().build() def jwe = builder.setSubject('joe').encryptWith(key, enc).compact() - def jwt = Jwts.parserBuilder().decryptWith(key).build().parseClaimsJwe(jwe) + def jwt = Jwts.parser().decryptWith(key).build().parseClaimsJwe(jwe) assertEquals 'joe', jwt.getPayload().getSubject() } diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtParserBuilderTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtParserBuilderTest.groovy index eedb82abe..eb217265c 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtParserBuilderTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtParserBuilderTest.groovy @@ -18,6 +18,7 @@ package io.jsonwebtoken.impl import com.fasterxml.jackson.databind.ObjectMapper import io.jsonwebtoken.* import io.jsonwebtoken.impl.security.ConstantKeyLocator +import io.jsonwebtoken.impl.security.LocatingKeyResolver import io.jsonwebtoken.impl.security.TestKeys import io.jsonwebtoken.io.Decoder import io.jsonwebtoken.io.DecodingException @@ -54,10 +55,24 @@ class DefaultJwtParserBuilderTest { def parser = builder.setProvider(provider).build() - assertSame provider, parser.jwtParser.provider + assertSame provider, parser.provider verify provider } + @Test + void testKeyLocatorAndVerificationKeyConfigured() { + try { + builder + .setKeyLocator(new ConstantKeyLocator(null, null)) + .verifyWith(TestKeys.HS256) + .build() + fail() + } catch (IllegalStateException e) { + String msg = "Both 'keyLocator' and a 'verifyWith' key cannot be configured. Prefer 'keyLocator' if possible." + assertEquals msg, e.getMessage() + } + } + @Test void testKeyLocatorAndDecryptionKeyConfigured() { try { @@ -67,7 +82,7 @@ class DefaultJwtParserBuilderTest { .build() fail() } catch (IllegalStateException e) { - String msg = "Both 'keyLocator' and 'decryptWith' key cannot be configured. Prefer 'keyLocator' if possible." + String msg = "Both 'keyLocator' and a 'decryptWith' key cannot be configured. Prefer 'keyLocator' if possible." assertEquals msg, e.getMessage() } } @@ -85,7 +100,7 @@ class DefaultJwtParserBuilderTest { return null } } - def b = builder.base64UrlDecodeWith(decoder) + def b = builder.base64UrlDecodeWith(decoder).build() assertSame decoder, b.base64UrlDecoder } @@ -139,7 +154,7 @@ class DefaultJwtParserBuilderTest { } } def parser = builder.setCompressionCodecResolver(resolver).build() - assertSame resolver, parser.jwtParser.compressionAlgorithmLocator.resolver + assertSame resolver, parser.zipAlgFn.resolver } @Test @@ -147,7 +162,7 @@ class DefaultJwtParserBuilderTest { def codec = new TestCompressionCodec(id: 'test') def parser = builder.addCompressionAlgorithms([codec] as Set).build() def header = Jwts.header().setCompressionAlgorithm(codec.getId()).build() - assertSame codec, parser.jwtParser.compressionAlgorithmLocator.locate(header) + assertSame codec, parser.zipAlgFn.locate(header) } @Test @@ -203,10 +218,7 @@ class DefaultJwtParserBuilderTest { @Test void testDefaultDeserializer() { JwtParser parser = builder.build() - assertThat parser.jwtParser.deserializer, CoreMatchers.instanceOf(JwtDeserializer) - - // TODO: When the ImmutableJwtParser replaces the default implementation this test will need updating, something like: - // assertThat parser.deserializer, CoreMatchers.instanceOf(JwtDeserializer) + assertThat parser.deserializer, CoreMatchers.instanceOf(JwtDeserializer) } @Test @@ -214,20 +226,19 @@ class DefaultJwtParserBuilderTest { Deserializer deserializer = niceMock(Deserializer) JwtParser parser = builder.deserializeJsonWith(deserializer).build() - // TODO: When the ImmutableJwtParser replaces the default implementation this test will need updating - assertThat parser.jwtParser.deserializer, CoreMatchers.instanceOf(JwtDeserializer) - assertSame deserializer, parser.jwtParser.deserializer.deserializer + assertThat parser.deserializer, CoreMatchers.instanceOf(JwtDeserializer) + assertSame deserializer, parser.deserializer.deserializer } @Test void testVerificationKeyAndSigningKeyResolverBothConfigured() { def key = TestKeys.HS256 - builder.verifyWith(key).setSigningKeyResolver(new ConstantKeyLocator(key, null)) + builder.verifyWith(key).setSigningKeyResolver(new LocatingKeyResolver(new ConstantKeyLocator(key, null))) try { builder.build() fail() } catch (IllegalStateException expected) { - String msg = "Both 'signingKeyResolver and 'verifyWith/signWith' key cannot be configured. " + "Choose either, or prefer `keyLocator` when possible." + String msg = "Both a 'signingKeyResolver and a 'verifyWith' key cannot be configured. " + "Choose either, or prefer `keyLocator` when possible." assertEquals(msg, expected.getMessage()) } } diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtParserTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtParserTest.groovy index 2dd71c253..2ed6cdb80 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtParserTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtParserTest.groovy @@ -20,7 +20,9 @@ import io.jsonwebtoken.Jwts import io.jsonwebtoken.MalformedJwtException import io.jsonwebtoken.SignatureAlgorithm import io.jsonwebtoken.impl.lang.Bytes -import io.jsonwebtoken.io.* +import io.jsonwebtoken.io.DeserializationException +import io.jsonwebtoken.io.Deserializer +import io.jsonwebtoken.io.Encoders import io.jsonwebtoken.lang.Strings import io.jsonwebtoken.security.Keys import org.junit.Test @@ -42,31 +44,13 @@ class DefaultJwtParserTest { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - @Test(expected = IllegalArgumentException) - void testBase64UrlDecodeWithNullArgument() { - new DefaultJwtParser().base64UrlDecodeWith(null) - } - - @Test - void testBase64UrlDecodeWithCustomDecoder() { - def decoder = new Decoder() { - @Override - Object decode(Object o) throws DecodingException { - return null - } - } - def b = new DefaultJwtParser().base64UrlDecodeWith(decoder) - assertSame decoder, b.base64UrlDecoder + private DefaultJwtParser newParser() { + return Jwts.parser().build() as DefaultJwtParser } @Test(expected = MalformedJwtException) void testBase64UrlDecodeWithInvalidInput() { - new DefaultJwtParser().base64UrlDecode('20:SLDKJF;3993;----', 'test') - } - - @Test(expected = IllegalArgumentException) - void testDeserializeJsonWithNullArgument() { - new DefaultJwtParser().deserializeJsonWith(null) + newParser().base64UrlDecode('20:SLDKJF;3993;----', 'test') } @Test @@ -77,15 +61,16 @@ class DefaultJwtParserTest { return OBJECT_MAPPER.readValue(bytes, Map.class) } } - def p = new DefaultJwtParser().deserializeJsonWith(deserializer) + def pb = Jwts.parser().deserializeJsonWith(deserializer) + def p = pb.build() as DefaultJwtParser assertTrue("Expected wrapping deserializer to be instance of JwtDeserializer", p.deserializer instanceof JwtDeserializer ) assertSame deserializer, p.deserializer.deserializer - def key = Keys.secretKeyFor(SignatureAlgorithm.HS256) + def key = Jwts.SIG.HS256.keyBuilder().build() - String jws = Jwts.builder().claim('foo', 'bar').signWith(key, SignatureAlgorithm.HS256).compact() + String jws = Jwts.builder().claim('foo', 'bar').signWith(key, Jwts.SIG.HS256).compact() - assertEquals 'bar', p.setSigningKey(key).parseClaimsJws(jws).getPayload().get('foo') + assertEquals 'bar', pb.verifyWith(key).build().parseClaimsJws(jws).getPayload().get('foo') } @Test(expected = MalformedJwtException) @@ -103,7 +88,7 @@ class DefaultJwtParserTest { String invalidJws = compact + encodedSignature - new DefaultJwtParser().setSigningKey(key).parseClaimsJws(invalidJws) + Jwts.parser().verifyWith(key).build().parseClaimsJws(invalidJws) } @Test(expected = MalformedJwtException) @@ -121,7 +106,7 @@ class DefaultJwtParserTest { String invalidJws = compact + encodedSignature - new DefaultJwtParser().setSigningKey(key).parseClaimsJws(invalidJws) + Jwts.parser().verifyWith(key).build().parseClaimsJwe(invalidJws) } @Test(expected = MalformedJwtException) @@ -139,24 +124,7 @@ class DefaultJwtParserTest { String invalidJws = compact + encodedSignature - new DefaultJwtParser().setSigningKey(key).parseClaimsJws(invalidJws) - } - - @Test - void testMaxAllowedClockSkewSeconds() { - long max = Long.MAX_VALUE / 1000 as long - new DefaultJwtParser().setAllowedClockSkewSeconds(max) // no exception should be thrown - } - - @Test - void testExceededAllowedClockSkewSeconds() { - long value = Long.MAX_VALUE / 1000 as long - value = value + 1L - try { - new DefaultJwtParser().setAllowedClockSkewSeconds(value) - } catch (IllegalArgumentException expected) { - assertEquals DefaultJwtParserBuilder.MAX_CLOCK_SKEW_ILLEGAL_MSG, expected.message - } + Jwts.parser().verifyWith(key).build().parseClaimsJws(invalidJws) } @Test diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtTest.groovy index 28c4786df..69c06b638 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/DefaultJwtTest.groovy @@ -30,7 +30,7 @@ class DefaultJwtTest { @Test void testToString() { String compact = Jwts.builder().setHeaderParam('foo', 'bar').setAudience('jsmith').compact() - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseClaimsJwt(compact) + Jwt jwt = Jwts.parser().enableUnsecuredJws().build().parseClaimsJwt(compact) assertEquals 'header={foo=bar, alg=none},payload={aud=jsmith}', jwt.toString() } @@ -39,14 +39,14 @@ class DefaultJwtTest { byte[] bytes = 'hello JJWT'.getBytes(StandardCharsets.UTF_8) String encoded = Encoders.BASE64URL.encode(bytes) String compact = Jwts.builder().setHeaderParam('foo', 'bar').setContent(bytes).compact() - Jwt jwt = Jwts.parserBuilder().enableUnsecuredJws().build().parseContentJwt(compact) + Jwt jwt = Jwts.parser().enableUnsecuredJws().build().parseContentJwt(compact) assertEquals "header={foo=bar, alg=none},payload=$encoded" as String, jwt.toString() } @Test void testEqualsAndHashCode() { String compact = Jwts.builder().claim('foo', 'bar').compact() - def parser = Jwts.parserBuilder().enableUnsecuredJws().build() + def parser = Jwts.parser().enableUnsecuredJws().build() def jwt1 = parser.parseClaimsJwt(compact) def jwt2 = parser.parseClaimsJwt(compact) assertNotEquals jwt1, 'hello' as String @@ -60,7 +60,7 @@ class DefaultJwtTest { @Test void testBodyAndPayloadSame() { String compact = Jwts.builder().claim('foo', 'bar').compact() - def parser = Jwts.parserBuilder().enableUnsecuredJws().build() + def parser = Jwts.parser().enableUnsecuredJws().build() def jwt1 = parser.parseClaimsJwt(compact) def jwt2 = parser.parseClaimsJwt(compact) assertEquals jwt1.getBody(), jwt1.getPayload() diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/ImmutableJwtParserTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/ImmutableJwtParserTest.groovy deleted file mode 100644 index 0ae6987e8..000000000 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/ImmutableJwtParserTest.groovy +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2019 jsonwebtoken.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.jsonwebtoken.impl - -import io.jsonwebtoken.* -import io.jsonwebtoken.io.Decoder -import io.jsonwebtoken.io.Deserializer -import org.junit.Test - -import java.security.Key - -import static org.easymock.EasyMock.* -import static org.hamcrest.CoreMatchers.is -import static org.hamcrest.MatcherAssert.assertThat - -/** - * TODO: These mutable methods will be removed pre 1.0, and ImmutableJwtParser will be replaced with the default - * JwtParser impl. - * - * @since 0.11.0 - */ -class ImmutableJwtParserTest { - - @Test - void parseWithHandlerTest() { - - def jwtString = "j.w.t" - JwtHandler jwtHandler = mock(JwtHandler) - JwtParser jwtParser = mock(JwtParser) - Object returnValue = new Object() - - expect(jwtParser.parse(jwtString, jwtHandler)).andReturn(returnValue) - replay(jwtParser) - - assertThat new ImmutableJwtParser(jwtParser).parse(jwtString, jwtHandler), is(returnValue) - - verify(jwtParser) - } - - private ImmutableJwtParser jwtParser() { - return new ImmutableJwtParser(mock(JwtParser)) - } - - @Test(expected=IllegalStateException) - void requireIdTest() { - jwtParser().requireId("id") - } - - @Test(expected=IllegalStateException) - void requireSubjectTest() { - jwtParser().requireSubject("subject") - } - - @Test(expected=IllegalStateException) - void requireAudienceTest() { - jwtParser().requireAudience("aud") - } - - @Test(expected=IllegalStateException) - void requireIssuerTest() { - jwtParser().requireIssuer("issuer") - } - - @Test(expected=IllegalStateException) - void requireIssuedAtTest() { - jwtParser().requireIssuedAt(new Date()) - } - - @Test(expected=IllegalStateException) - void requireExpirationTest() { - jwtParser().requireExpiration(new Date()) - } - - @Test(expected=IllegalStateException) - void requireNotBeforeTest() { - jwtParser().requireNotBefore(new Date()) - } - - @Test(expected=IllegalStateException) - void requireTest() { - jwtParser().require("key", "value") - } - - @Test(expected=IllegalStateException) - void setClockTest() { - jwtParser().setClock(mock((Clock))) - } - - @Test(expected=IllegalStateException) - void setAllowedClockSkewSecondsTest() { - jwtParser().setAllowedClockSkewSeconds(1L) - } - - @Test(expected=IllegalStateException) - void setSigningKeyBytesTest() { - jwtParser().setSigningKey("foo".getBytes()) - } - - @Test(expected=IllegalStateException) - void setSigningKeyStringTest() { - jwtParser().setSigningKey("foo") - } - - @Test(expected=IllegalStateException) - void setSigningKey() { - jwtParser().setSigningKey(mock(Key)) - } - - @Test(expected=IllegalStateException) - void setSigningKeyResolverTest() { - jwtParser().setSigningKeyResolver(mock(SigningKeyResolver)) - } - - @Test(expected=IllegalStateException) - void setCompressionCodecResolverTest() { - jwtParser().setCompressionCodecResolver(mock(CompressionCodecResolver)) - } - - @Test(expected=IllegalStateException) - void base64UrlDecodeWithTest() { - jwtParser().base64UrlDecodeWith(mock(Decoder)) - } - - @Test(expected=IllegalStateException) - void deserializeJsonWithTest() { - jwtParser().deserializeJsonWith(mock(Deserializer)) - } -} diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/compression/DeflateCompressionCodecTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/compression/DeflateCompressionCodecTest.groovy index 3dd30a9ee..184466ae9 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/compression/DeflateCompressionCodecTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/compression/DeflateCompressionCodecTest.groovy @@ -33,7 +33,7 @@ class DeflateCompressionCodecTest { @Test void testBackwardsCompatibility_0_10_6() { final String jwtFrom0106 = 'eyJhbGciOiJub25lIiwiemlwIjoiREVGIn0.eNqqVsosLlayUspNVdJRKi5NAjJLi1OLgJzMxBIlK0sTMzMLEwsDAx2l1IoCJSsTQwMjExOQQC0AAAD__w.' - Jwts.parserBuilder().enableUnsecuredJws().enableUnsecuredDecompression().build().parseClaimsJwt(jwtFrom0106) // no exception should be thrown + Jwts.parser().enableUnsecuredJws().enableUnsecuredDecompression().build().parseClaimsJwt(jwtFrom0106) // no exception should be thrown } /** diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/lang/LegacyServicesTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/lang/LegacyServicesTest.groovy deleted file mode 100644 index 264e43c24..000000000 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/lang/LegacyServicesTest.groovy +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2021 jsonwebtoken.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.jsonwebtoken.impl.lang - -import io.jsonwebtoken.lang.UnknownClassException -import org.junit.Test - -class LegacyServicesTest { - - @Test(expected = UnknownClassException) - void serviceNotFoundTest() { - // try to load a class that will NOT have any services, i.e. this test class. - LegacyServices.loadFirst(LegacyServicesTest) - } -} diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/EdSignatureAlgorithmTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/EdSignatureAlgorithmTest.groovy index ff9936c0a..50465bf6c 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/EdSignatureAlgorithmTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/EdSignatureAlgorithmTest.groovy @@ -138,7 +138,7 @@ class EdSignatureAlgorithmTest { static void testSig(SignatureAlgorithm alg, PrivateKey signing, PublicKey verification) { String jwt = Jwts.builder().setIssuer('me').setAudience('you').signWith(signing, alg).compact() - def token = Jwts.parserBuilder().verifyWith(verification).build().parseClaimsJws(jwt) + def token = Jwts.parser().verifyWith(verification).build().parseClaimsJws(jwt) assertEquals([alg: alg.getId()], token.header) assertEquals 'me', token.getPayload().getIssuer() assertEquals 'you', token.getPayload().getAudience() diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/Issue542Test.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/Issue542Test.groovy index 4c2c7b7ce..f38333d31 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/Issue542Test.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/Issue542Test.groovy @@ -56,7 +56,7 @@ class Issue542Test { for (alg in algs) { PublicKey key = TestKeys.forAlgorithm(alg).pair.public String jws = JWS_0_10_7_VALUES[alg] - def token = Jwts.parserBuilder().verifyWith(key).build().parseClaimsJws(jws) + def token = Jwts.parser().verifyWith(key).build().parseClaimsJws(jws) assert 'joe' == token.payload.getIssuer() } } diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA1Test.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA1Test.groovy index 4ceee9d40..9f721f9a3 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA1Test.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA1Test.groovy @@ -174,7 +174,7 @@ class RFC7516AppendixA1Test { RsaPrivateJwk jwk = Jwks.builder().set(KEK_VALUES).build() as RsaPrivateJwk RSAPrivateKey privKey = jwk.toKey() - Jwe jwe = Jwts.parserBuilder().decryptWith(privKey).build().parseContentJwe(COMPLETE_JWE) + Jwe jwe = Jwts.parser().decryptWith(privKey).build().parseContentJwe(COMPLETE_JWE) assertEquals PLAINTEXT, new String(jwe.getPayload(), StandardCharsets.UTF_8) } } diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA2Test.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA2Test.groovy index 4880c909b..0734932ac 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA2Test.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA2Test.groovy @@ -168,7 +168,7 @@ class RFC7516AppendixA2Test { RsaPrivateJwk jwk = Jwks.builder().set(KEK_VALUES).build() as RsaPrivateJwk RSAPrivateKey privKey = jwk.toKey() - Jwe jwe = Jwts.parserBuilder().decryptWith(privKey).build().parseContentJwe(COMPLETE_JWE) + Jwe jwe = Jwts.parser().decryptWith(privKey).build().parseContentJwe(COMPLETE_JWE) assertEquals PLAINTEXT, new String(jwe.getPayload(), StandardCharsets.UTF_8) } } diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA3Test.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA3Test.groovy index ff75182b7..7ea4022fe 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA3Test.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7516AppendixA3Test.groovy @@ -109,7 +109,7 @@ class RFC7516AppendixA3Test { SecretKey kek = jwk.toKey() // test decryption per the RFC - Jwe jwe = Jwts.parserBuilder().decryptWith(kek).build().parseContentJwe(COMPLETE_JWE) + Jwe jwe = Jwts.parser().decryptWith(kek).build().parseContentJwe(COMPLETE_JWE) assertEquals PLAINTEXT, new String(jwe.getPayload(), StandardCharsets.UTF_8) // now ensure that when JJWT does the encryption (i.e. a compact value is produced from JJWT, not from the RFC text), diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7517AppendixCTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7517AppendixCTest.groovy index e81336843..b5303a34b 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7517AppendixCTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7517AppendixCTest.groovy @@ -331,7 +331,7 @@ class RFC7517AppendixCTest { assertEquals RFC_COMPACT_JWE, compact //ensure we can decrypt now: - Jwe jwe = Jwts.parserBuilder().decryptWith(key).build().parseContentJwe(compact) + Jwe jwe = Jwts.parser().decryptWith(key).build().parseContentJwe(compact) assertEquals RFC_JWK_JSON, new String(jwe.getPayload(), StandardCharsets.UTF_8) } diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7518AppendixCTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7518AppendixCTest.groovy index bad76beb0..9880e3f7d 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7518AppendixCTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7518AppendixCTest.groovy @@ -126,7 +126,7 @@ class RFC7518AppendixCTest { assertArrayEquals RFC_DERIVED_KEY, derivedKey // now reverse the process and ensure it all works: - Jwe claimsJwe = Jwts.parserBuilder() + Jwe claimsJwe = Jwts.parser() .decryptWith(bobJwk.toKey()) .build().parseClaimsJwe(jwe) diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7520Section4Test.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7520Section4Test.groovy index e3124a8be..aa827f95d 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7520Section4Test.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7520Section4Test.groovy @@ -227,7 +227,7 @@ class RFC7520Section4Test { assertEquals FIGURE_13, result // Assert round trip works as expected: - def parsed = Jwts.parserBuilder().verifyWith(jwk.toPublicJwk().toKey()).build().parseContentJws(result) + def parsed = Jwts.parser().verifyWith(jwk.toPublicJwk().toKey()).build().parseContentJws(result) assertEquals alg.getId(), parsed.header.getAlgorithm() assertEquals jwk.getId(), parsed.header.getKeyId() assertEquals FIGURE_7, utf8(parsed.payload) @@ -271,7 +271,7 @@ class RFC7520Section4Test { // even though we can't know what the signature output is ahead of time due to random data, we can assert // the signature to guarantee a round trip works as expected: - def parsed = Jwts.parserBuilder() + def parsed = Jwts.parser() .verifyWith(jwk.toPublicJwk().toKey()) .build().parseContentJws(result) @@ -316,7 +316,7 @@ class RFC7520Section4Test { // even though we can't know what the signature output is ahead of time due to random data, we can assert // the signature to guarantee a round trip works as expected: - def parsed = Jwts.parserBuilder() + def parsed = Jwts.parser() .verifyWith(jwk.toPublicJwk().toKey()) .build().parseContentJws(result) @@ -357,7 +357,7 @@ class RFC7520Section4Test { assertEquals FIGURE_34, result // Assert round trip works as expected: - def parsed = Jwts.parserBuilder().verifyWith(key).build().parseContentJws(result) + def parsed = Jwts.parser().verifyWith(key).build().parseContentJws(result) assertEquals alg.getId(), parsed.header.getAlgorithm() assertEquals jwk.getId(), parsed.header.getKeyId() assertEquals FIGURE_7, utf8(parsed.payload) @@ -398,7 +398,7 @@ class RFC7520Section4Test { assertEquals FIGURE_41, detached // Assert round trip works as expected: - def parsed = Jwts.parserBuilder().verifyWith(key).build().parseContentJws(result) + def parsed = Jwts.parser().verifyWith(key).build().parseContentJws(result) assertEquals alg.getId(), parsed.header.getAlgorithm() assertEquals jwk.getId(), parsed.header.getKeyId() assertEquals FIGURE_7, utf8(parsed.payload) diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7520Section5Test.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7520Section5Test.groovy index 1fbe2abbd..89d2d2a11 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7520Section5Test.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC7520Section5Test.groovy @@ -481,7 +481,7 @@ class RFC7520Section5Test { assertEquals FIGURE_81, result // Assert round trip works as expected: - def parsed = Jwts.parserBuilder().decryptWith(jwk.toKey()).build().parseContentJwe(result) + def parsed = Jwts.parser().decryptWith(jwk.toKey()).build().parseContentJwe(result) assertEquals alg.getId(), parsed.header.getAlgorithm() assertEquals jwk.getId(), parsed.header.getKeyId() assertEquals enc.getId(), parsed.header.getEncryptionAlgorithm() @@ -545,7 +545,7 @@ class RFC7520Section5Test { assertEquals FIGURE_92, result // Assert round trip works as expected: - def parsed = Jwts.parserBuilder().decryptWith(jwk.toKey()).build().parseContentJwe(result) + def parsed = Jwts.parser().decryptWith(jwk.toKey()).build().parseContentJwe(result) assertEquals alg.getId(), parsed.header.getAlgorithm() assertEquals jwk.getId(), parsed.header.getKeyId() assertEquals enc.getId(), parsed.header.getEncryptionAlgorithm() @@ -606,7 +606,7 @@ class RFC7520Section5Test { assertEquals FIGURE_105, result // Assert round trip works as expected: - def parsed = Jwts.parserBuilder().decryptWith(key).build().parseContentJwe(result) + def parsed = Jwts.parser().decryptWith(key).build().parseContentJwe(result) assertEquals alg.getId(), parsed.header.getAlgorithm() assertEquals FIGURE_99, b64Url(parsed.header.getPbes2Salt()) assertEquals p2c, parsed.header.getPbes2Count() @@ -668,7 +668,7 @@ class RFC7520Section5Test { assertEquals FIGURE_117, result // Assert round trip works as expected: - def parsed = Jwts.parserBuilder().decryptWith(jwk.toKey()).build().parseContentJwe(result) + def parsed = Jwts.parser().decryptWith(jwk.toKey()).build().parseContentJwe(result) assertEquals alg.getId(), parsed.header.getAlgorithm() assertEquals enc.getId(), parsed.header.getEncryptionAlgorithm() assertEquals jwk.getId(), parsed.header.getKeyId() diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC8037AppendixATest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC8037AppendixATest.groovy index e86dabdd7..7e6f99da1 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC8037AppendixATest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/security/RFC8037AppendixATest.groovy @@ -108,7 +108,7 @@ class RFC8037AppendixATest { assertEquals A4_JWS_COMPACT, compact def pubJwk = a2Jwk() - def payloadBytes = Jwts.parserBuilder().verifyWith(pubJwk.toKey()).build().parse(compact).getPayload() as byte[] + def payloadBytes = Jwts.parser().verifyWith(pubJwk.toKey()).build().parse(compact).getPayload() as byte[] def payload = new String(payloadBytes, StandardCharsets.UTF_8) assertEquals A4_JWS_PAYLOAD, payload } @@ -193,7 +193,7 @@ class RFC8037AppendixATest { assertEquals(rfcExpectedHeaderMap.get('epk'), jweHeaderMap.get('epk')) //ensure that bob can decrypt: - def jwt = Jwts.parserBuilder().decryptWith(bobPrivJwk.toKey() as PrivateKey).build().parseClaimsJwe(jwe) + def jwt = Jwts.parser().decryptWith(bobPrivJwk.toKey() as PrivateKey).build().parseClaimsJwe(jwe) assertEquals(issuer, jwt.getPayload().getIssuer()) } @@ -284,7 +284,7 @@ class RFC8037AppendixATest { assertEquals(rfcExpectedHeaderMap.get('epk'), jweHeaderMap.get('epk')) //ensure that Bob ("Dave") can decrypt: - def jwt = Jwts.parserBuilder().decryptWith(bobPrivJwk.toKey() as PrivateKey).build().parseClaimsJwe(jwe) + def jwt = Jwts.parser().decryptWith(bobPrivJwk.toKey() as PrivateKey).build().parseClaimsJwe(jwe) //assert that we've decrypted and the value in the body/content is as expected: assertEquals(issuer, jwt.getPayload().getIssuer()) diff --git a/tdjar/src/test/groovy/io/jsonwebtoken/all/BasicTest.groovy b/tdjar/src/test/groovy/io/jsonwebtoken/all/BasicTest.groovy index bf1ffaa39..258abeae3 100644 --- a/tdjar/src/test/groovy/io/jsonwebtoken/all/BasicTest.groovy +++ b/tdjar/src/test/groovy/io/jsonwebtoken/all/BasicTest.groovy @@ -38,7 +38,7 @@ class BasicTest { .signWith(key, SignatureAlgorithm.HS256) .compact() - JwtParser parser = Jwts.parserBuilder() + JwtParser parser = Jwts.parser() .setSigningKey(key) .build() diff --git a/tdjar/src/test/java/io/jsonwebtoken/all/JavaReadmeTest.java b/tdjar/src/test/java/io/jsonwebtoken/all/JavaReadmeTest.java index 542810ac4..d1850ea49 100644 --- a/tdjar/src/test/java/io/jsonwebtoken/all/JavaReadmeTest.java +++ b/tdjar/src/test/java/io/jsonwebtoken/all/JavaReadmeTest.java @@ -70,7 +70,7 @@ public void testExampleJwsHS() { String jws = Jwts.builder().setContent(content, "text/plain").signWith(key, alg).compact(); // Parse the compact JWS: - content = Jwts.parserBuilder().verifyWith(key).build().parseContentJws(jws).getPayload(); + content = Jwts.parser().verifyWith(key).build().parseContentJws(jws).getPayload(); assert message.equals(new String(content, StandardCharsets.UTF_8)); } @@ -90,7 +90,7 @@ public void testExampleJwsRSA() { .compact(); // Alice receives and verifies the compact JWS came from Bob: - String subject = Jwts.parserBuilder() + String subject = Jwts.parser() .verifyWith(pair.getPublic()) // <-- Bob's RSA public key .build().parseClaimsJws(jws).getPayload().getSubject(); @@ -112,7 +112,7 @@ public void testExampleJwsECDSA() { .compact(); // Alice receives and verifies the compact JWS came from Bob: - String subject = Jwts.parserBuilder() + String subject = Jwts.parser() .verifyWith(pair.getPublic()) // <-- Bob's EC public key .build().parseClaimsJws(jws).getPayload().getSubject(); @@ -136,7 +136,7 @@ public void testExampleJweDir() { String jwe = Jwts.builder().setContent(content, "text/plain").encryptWith(key, enc).compact(); // Parse the compact JWE: - content = Jwts.parserBuilder().decryptWith(key).build().parseContentJwe(jwe).getPayload(); + content = Jwts.parser().decryptWith(key).build().parseContentJwe(jwe).getPayload(); assert message.equals(new String(content, StandardCharsets.UTF_8)); } @@ -160,7 +160,7 @@ public void testExampleJweRSA() { .compact(); // Alice receives and decrypts the compact JWE: - String audience = Jwts.parserBuilder() + String audience = Jwts.parser() .decryptWith(pair.getPrivate()) // <-- Alice's RSA private key .build().parseClaimsJwe(jwe).getPayload().getAudience(); @@ -183,7 +183,7 @@ public void testExampleJweAESKW() { String jwe = Jwts.builder().setIssuer("me").encryptWith(key, alg, enc).compact(); // Parse the compact JWE: - String issuer = Jwts.parserBuilder().decryptWith(key).build() + String issuer = Jwts.parser().decryptWith(key).build() .parseClaimsJwe(jwe).getPayload().getIssuer(); assert "me".equals(issuer); @@ -208,7 +208,7 @@ public void testExampleJweECDHES() { .compact(); // Alice receives and decrypts the compact JWE: - String audience = Jwts.parserBuilder() + String audience = Jwts.parser() .decryptWith(pair.getPrivate()) // <-- Alice's EC private key .build().parseClaimsJwe(jwe).getPayload().getAudience(); @@ -246,7 +246,7 @@ public void testExampleJwePassword() { .compact(); // Parse the compact JWE: - String issuer = Jwts.parserBuilder().decryptWith(password) + String issuer = Jwts.parser().decryptWith(password) .build().parseClaimsJwe(jwe).getPayload().getIssuer(); assert "me".equals(issuer);