mirror of
https://github.com/jwtk/jjwt.git
synced 2025-02-10 07:54:42 +00:00
Merge pull request #5 from jwtk/JwtHandler
Add JwtHandler for JWT/JWS type-specific handling
This commit is contained in:
commit
af4bb5a820
82
README.md
82
README.md
@ -22,7 +22,7 @@ Note: JJWT depends on Jackson 2.x. If you're already using an older version of
|
||||
|
||||
## Usage
|
||||
|
||||
Most complexity is hidden behind convenient and readable Builder chaining calls. Here's an example:
|
||||
Most complexity is hidden behind a convenient and readable builder-based [fluent interface](http://en.wikipedia.org/wiki/Fluent_interface), great for relying on IDE auto-completion to write code quickly. Here's an example:
|
||||
|
||||
```java
|
||||
import io.jsonwebtoken.Jwts;
|
||||
@ -108,6 +108,86 @@ String compactJwt = Jwts.builder().setSubject("Joe").signWith(HS256, key).compac
|
||||
|
||||
A Claims instance based on the specified claims will be created and set as the JWT's payload automatically.
|
||||
|
||||
#### Type-safe handling for JWT and JWS with generics
|
||||
|
||||
The following < 0.2 code produced a JWT as expected:
|
||||
|
||||
```java
|
||||
Jwt jwt = Jwts.parser().setSigningKey(key).parse(compact);
|
||||
```
|
||||
|
||||
But you couldn't easily determine if the `jwt` was a `JWT` or `JWS` instance or if the body was a `Claims` instance or a plaintext `String` without resorting to a bunch of yucky `instanceof` checks. In 0.2, we introduce the `JwtHandler` when you don't know the exact format of the compact JWT string ahead of time, and parsing convenience methods when you do.
|
||||
|
||||
##### JwtHandler
|
||||
|
||||
If you do not know the format of the compact JWT string at the time you try to parse it, you can determine what type it is after parsing by providing a `JwtHandler` instance to the `JwtParser` with the new `parse(String compactJwt, JwtHandler handler)` method. For example:
|
||||
|
||||
```java
|
||||
T returnVal = Jwts.parser().setSigningKey(key).parse(compact, new JwtHandler<T>() {
|
||||
@Override
|
||||
public Object onPlaintextJwt(Jwt<Header, String> jwt) {
|
||||
//the JWT parsed was an unsigned plaintext JWT
|
||||
//inspect it, then return an instance of T (see returnVal above)
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onClaimsJwt(Jwt<Header, Claims> jwt) {
|
||||
//the JWT parsed was an unsigned Claims JWT
|
||||
//inspect it, then return an instance of T (see returnVal above)
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onPlaintextJws(Jws<String> jws) {
|
||||
//the JWT parsed was a signed plaintext JWS
|
||||
//inspect it, then return an instance of T (see returnVal above)
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onClaimsJws(Jws<Claims> jws) {
|
||||
//the JWT parsed was a signed Claims JWS
|
||||
//inspect it, then return an instance of T (see returnVal above)
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Of course, if you know you'll only have to parse a subset of the above, you can use the `JwtHandlerAdapter` and implement only the methods you need. For example:
|
||||
|
||||
```java
|
||||
T returnVal = Jwts.parser().setSigningKey(key).parse(plaintextJwt, new JwtHandlerAdapter<Jwt<Header, T>>() {
|
||||
@Override
|
||||
public Object onPlaintextJws(Jws<String> jws) {
|
||||
//the JWT parsed was a signed plaintext JWS
|
||||
//inspect it, then return an instance of T (see returnVal above)
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onClaimsJws(Jws<Claims> jws) {
|
||||
//the JWT parsed was a signed Claims JWS
|
||||
//inspect it, then return an instance of T (see returnVal above)
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
##### Known Type convenience parse methods
|
||||
|
||||
If, unlike above, you are confident of the compact string format and know which type of JWT or JWS it will produce, you can just use one of the 4 new convenience parsing methods to get exactly the type of JWT or JWS you know exists. For example:
|
||||
|
||||
```java
|
||||
|
||||
//for a known plaintext jwt string:
|
||||
Jwt<Header,String> jwt = Jwts.parser().parsePlaintextJwt(compact);
|
||||
|
||||
//for a known Claims JWT string:
|
||||
Jwt<Header,Claims> jwt = Jwts.parser().parseClaimsJwt(compact);
|
||||
|
||||
//for a known signed plaintext JWT (aka a plaintext JWS):
|
||||
Jws<String> jws = Jwts.parser().setSigningKey(key).parsePlaintextJws(compact);
|
||||
|
||||
//for a known signed Claims JWT (aka a Claims JWS):
|
||||
Jws<Claims> jws = Jwts.parser().setSigningKey(key).parseClaimsJws(compact);
|
||||
|
||||
```
|
||||
|
||||
<a name="olderJackson"></a>
|
||||
#### Already using an older Jackson dependency?
|
||||
|
||||
|
68
src/main/java/io/jsonwebtoken/JwtHandler.java
Normal file
68
src/main/java/io/jsonwebtoken/JwtHandler.java
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A JwtHandler is invoked by a {@link io.jsonwebtoken.JwtParser JwtParser} after parsing a JWT to indicate the exact
|
||||
* type of JWT or JWS parsed.
|
||||
*
|
||||
* @param <T> the type of object to return to the parser caller after handling the parsed JWT.
|
||||
* @since 0.2
|
||||
*/
|
||||
public interface JwtHandler<T> {
|
||||
|
||||
/**
|
||||
* This method is invoked when a {@link io.jsonwebtoken.JwtParser JwtParser} determines that the parsed JWT is
|
||||
* a plaintext JWT. A plaintext JWT has a String (non-JSON) body payload and it is not cryptographically signed.
|
||||
*
|
||||
* @param jwt the parsed plaintext JWT
|
||||
* @return any object to be used after inspecting the JWT, or {@code null} if no return value is necessary.
|
||||
*/
|
||||
T onPlaintextJwt(Jwt<Header, String> jwt);
|
||||
|
||||
/**
|
||||
* This method is invoked when a {@link io.jsonwebtoken.JwtParser JwtParser} determines that the parsed JWT is
|
||||
* a Claims JWT. A Claims JWT has a {@link Claims} body and it is not cryptographically signed.
|
||||
*
|
||||
* @param jwt the parsed claims JWT
|
||||
* @return any object to be used after inspecting the JWT, or {@code null} if no return value is necessary.
|
||||
*/
|
||||
T onClaimsJwt(Jwt<Header, Claims> jwt);
|
||||
|
||||
/**
|
||||
* This method is invoked when a {@link io.jsonwebtoken.JwtParser JwtParser} determines that the parsed JWT is
|
||||
* a plaintext JWS. A plaintext JWS is a JWT with a String (non-JSON) body (payload) that has been
|
||||
* cryptographically signed.
|
||||
*
|
||||
* <p>This method will only be invoked if the cryptographic signature can be successfully verified.</p>
|
||||
*
|
||||
* @param jws the parsed plaintext JWS
|
||||
* @return any object to be used after inspecting the JWS, or {@code null} if no return value is necessary.
|
||||
*/
|
||||
T onPlaintextJws(Jws<String> jws);
|
||||
|
||||
/**
|
||||
* This method is invoked when a {@link io.jsonwebtoken.JwtParser JwtParser} determines that the parsed JWT is
|
||||
* a valid Claims JWS. A Claims JWS is a JWT with a {@link Claims} body that has been cryptographically signed.
|
||||
*
|
||||
* <p>This method will only be invoked if the cryptographic signature can be successfully verified.</p>
|
||||
*
|
||||
* @param jws the parsed claims JWS
|
||||
* @return any object to be used after inspecting the JWS, or {@code null} if no return value is necessary.
|
||||
*/
|
||||
T onClaimsJws(Jws<Claims> jws);
|
||||
|
||||
}
|
52
src/main/java/io/jsonwebtoken/JwtHandlerAdapter.java
Normal file
52
src/main/java/io/jsonwebtoken/JwtHandlerAdapter.java
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* An <a href="http://en.wikipedia.org/wiki/Adapter_pattern">Adapter</a> implementation of the
|
||||
* {@link JwtHandler} interface that allows for anonymous subclasses to process only the JWT results that are
|
||||
* known/expected for a particular use case.
|
||||
*
|
||||
* <p>All of the methods in this implementation throw exceptions: overridden methods represent
|
||||
* scenarios expected by calling code in known situations. It would be unexpected to receive a JWS or JWT that did
|
||||
* not match parsing expectations, so all non-overridden methods throw exceptions to indicate that the JWT
|
||||
* input was unexpected.</p>
|
||||
*
|
||||
* @param <T> the type of object to return to the parser caller after handling the parsed JWT.
|
||||
* @since 0.2
|
||||
*/
|
||||
public class JwtHandlerAdapter<T> implements JwtHandler<T> {
|
||||
|
||||
@Override
|
||||
public T onPlaintextJwt(Jwt<Header, String> jwt) {
|
||||
throw new UnsupportedJwtException("Unsigned plaintext JWTs are not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public T onClaimsJwt(Jwt<Header, Claims> jwt) {
|
||||
throw new UnsupportedJwtException("Unsigned Claims JWTs are not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public T onPlaintextJws(Jws<String> jws) {
|
||||
throw new UnsupportedJwtException("Signed plaintext JWSs are not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public T onClaimsJws(Jws<Claims> jws) {
|
||||
throw new UnsupportedJwtException("Signed Claims JWSs are not supported.");
|
||||
}
|
||||
}
|
@ -81,6 +81,9 @@ public interface JwtParser {
|
||||
* Returns {@code true} if the specified JWT compact string represents a signed JWT (aka a 'JWS'), {@code false}
|
||||
* otherwise.
|
||||
*
|
||||
* <p>Note that if you are reasonably sure that the token is signed, it is usually more efficient to attempt to
|
||||
* parse the token (and catching exceptions if necessary) instead of calling this method first before parsing.</p>
|
||||
*
|
||||
* @param jwt the compact serialized JWT to check
|
||||
* @return {@code true} if the specified JWT compact string represents a signed JWT (aka a 'JWS'), {@code false}
|
||||
* otherwise.
|
||||
@ -88,14 +91,188 @@ public interface JwtParser {
|
||||
boolean isSigned(String jwt);
|
||||
|
||||
/**
|
||||
* Parses the specified compact serialized JWT string based on the builder's current configuration state.
|
||||
* Parses the specified compact serialized JWT string based on the builder's current configuration state and
|
||||
* returns the resulting JWT or JWS instance.
|
||||
*
|
||||
* <p>This method returns a JWT or JWS based on the parsed string. Because it may be cumbersome to determine if it
|
||||
* is a JWT or JWS, or if the body/payload is a Claims or String with {@code instanceof} checks, the
|
||||
* {@link #parse(String, JwtHandler) parse(String,JwtHandler)} method allows for a type-safe callback approach that
|
||||
* may help reduce code or instanceof checks.</p>
|
||||
*
|
||||
* @param jwt the compact serialized JWT to parse
|
||||
* @return the specified compact serialized JWT string based on the builder's current configuration state.
|
||||
* @throws MalformedJwtException if the specified JWT was incorrectly constructed (and therefore invalid). Invalid
|
||||
* JWTs should not be trusted and should be discarded.
|
||||
* @throws SignatureException if a JWS signature was discovered, but could not be verified. JWTs that fail
|
||||
* signature validation should not be trusted and should be discarded.
|
||||
* @throws MalformedJwtException if the specified JWT was incorrectly constructed (and therefore invalid).
|
||||
* Invalid
|
||||
* JWTs should not be trusted and should be discarded.
|
||||
* @throws SignatureException if a JWS signature was discovered, but could not be verified. JWTs that fail
|
||||
* signature validation should not be trusted and should be discarded.
|
||||
* @throws IllegalArgumentException if the specified string is {@code null} or empty or only whitespace.
|
||||
* @see #parse(String, JwtHandler)
|
||||
* @see #parsePlaintextJwt(String)
|
||||
* @see #parseClaimsJwt(String)
|
||||
* @see #parsePlaintextJws(String)
|
||||
* @see #parseClaimsJws(String)
|
||||
*/
|
||||
Jwt parse(String jwt) throws MalformedJwtException, SignatureException;
|
||||
Jwt parse(String jwt) throws MalformedJwtException, SignatureException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Parses the specified compact serialized JWT string based on the builder's current configuration state and
|
||||
* invokes the specified {@code handler} with the resulting JWT or JWS instance.
|
||||
*
|
||||
* <p>If you are confident of the format of the JWT before parsing, you can create an anonymous subclass using the
|
||||
* {@link io.jsonwebtoken.JwtHandlerAdapter JwtHandlerAdapter} and override only the methods you know are relevant
|
||||
* for your use case(s), for example:</p>
|
||||
*
|
||||
* <pre>
|
||||
* String compactJwt = request.getParameter("jwt"); //we are confident this is a signed JWS
|
||||
*
|
||||
* String subject = Jwts.parser().setSigningKey(key).parse(compactJwt, new JwtHandlerAdapter<String>() {
|
||||
* @Override
|
||||
* public String onClaimsJws(Jws<Claims> jws) {
|
||||
* return jws.getBody().getSubject();
|
||||
* }
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* <p>If you know the JWT string can be only one type of JWT, then it is even easier to invoke one of the
|
||||
* following convenience methods instead of this one:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link #parsePlaintextJwt(String)}</li>
|
||||
* <li>{@link #parseClaimsJwt(String)}</li>
|
||||
* <li>{@link #parsePlaintextJws(String)}</li>
|
||||
* <li>{@link #parseClaimsJws(String)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param jwt the compact serialized JWT to parse
|
||||
* @return the result returned by the {@code JwtHandler}
|
||||
* @throws MalformedJwtException if the specified JWT was incorrectly constructed (and therefore invalid).
|
||||
* Invalid JWTs should not be trusted and should be discarded.
|
||||
* @throws SignatureException if a JWS signature was discovered, but could not be verified. JWTs that fail
|
||||
* signature validation should not be trusted and should be discarded.
|
||||
* @throws IllegalArgumentException if the specified string is {@code null} or empty or only whitespace, or if the
|
||||
* {@code handler} is {@code null}.
|
||||
* @see #parsePlaintextJwt(String)
|
||||
* @see #parseClaimsJwt(String)
|
||||
* @see #parsePlaintextJws(String)
|
||||
* @see #parseClaimsJws(String)
|
||||
* @see #parse(String)
|
||||
* @since 0.2
|
||||
*/
|
||||
<T> T parse(String jwt, JwtHandler<T> handler)
|
||||
throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Parses the specified compact serialized JWT string based on the builder's current configuration state and
|
||||
* returns
|
||||
* the resulting unsigned plaintext JWT instance.
|
||||
*
|
||||
* <p>This is a convenience method that is usable if you are confident that the compact string argument reflects an
|
||||
* unsigned plaintext JWT. An unsigned plaintext JWT has a String (non-JSON) body payload and it is not
|
||||
* cryptographically signed.</p>
|
||||
*
|
||||
* <p><b>If the compact string presented does not reflect an unsigned plaintext JWT with non-JSON string body,
|
||||
* an {@link UnsupportedJwtException} will be thrown.</b></p>
|
||||
*
|
||||
* @param plaintextJwt a compact serialized unsigned plaintext JWT string.
|
||||
* @return the {@link Jwt Jwt} instance that reflects the specified compact JWT string.
|
||||
* @throws UnsupportedJwtException if the {@code plaintextJwt} argument does not represent an unsigned plaintext
|
||||
* JWT
|
||||
* @throws MalformedJwtException if the {@code plaintextJwt} string is not a valid JWT
|
||||
* @throws SignatureException if the {@code plaintextJwt} string is actually a JWS and signature validation
|
||||
* fails
|
||||
* @throws IllegalArgumentException if the {@code plaintextJwt} string is {@code null} or empty or only whitespace
|
||||
* @see #parseClaimsJwt(String)
|
||||
* @see #parsePlaintextJws(String)
|
||||
* @see #parseClaimsJws(String)
|
||||
* @see #parse(String, JwtHandler)
|
||||
* @see #parse(String)
|
||||
* @since 0.2
|
||||
*/
|
||||
Jwt<Header, String> parsePlaintextJwt(String plaintextJwt)
|
||||
throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Parses the specified compact serialized JWT string based on the builder's current configuration state and
|
||||
* returns
|
||||
* the resulting unsigned plaintext JWT instance.
|
||||
*
|
||||
* <p>This is a convenience method that is usable if you are confident that the compact string argument reflects an
|
||||
* unsigned Claims JWT. An unsigned Claims JWT has a {@link Claims} body and it is not cryptographically
|
||||
* signed.</p>
|
||||
*
|
||||
* <p><b>If the compact string presented does not reflect an unsigned Claims JWT, an
|
||||
* {@link UnsupportedJwtException} will be thrown.</b></p>
|
||||
*
|
||||
* @param claimsJwt a compact serialized unsigned Claims JWT string.
|
||||
* @return the {@link Jwt Jwt} instance that reflects the specified compact JWT string.
|
||||
* @throws UnsupportedJwtException if the {@code claimsJwt} argument does not represent an unsigned Claims JWT
|
||||
* @throws MalformedJwtException if the {@code claimsJwt} string is not a valid JWT
|
||||
* @throws SignatureException if the {@code claimsJwt} string is actually a JWS and signature validation
|
||||
* fails
|
||||
* @throws IllegalArgumentException if the {@code claimsJwt} string is {@code null} or empty or only whitespace
|
||||
* @see #parsePlaintextJwt(String)
|
||||
* @see #parsePlaintextJws(String)
|
||||
* @see #parseClaimsJws(String)
|
||||
* @see #parse(String, JwtHandler)
|
||||
* @see #parse(String)
|
||||
* @since 0.2
|
||||
*/
|
||||
Jwt<Header, Claims> parseClaimsJwt(String claimsJwt)
|
||||
throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Parses the specified compact serialized JWS string based on the builder's current configuration state and
|
||||
* returns
|
||||
* the resulting plaintext JWS instance.
|
||||
*
|
||||
* <p>This is a convenience method that is usable if you are confident that the compact string argument reflects a
|
||||
* plaintext JWS. A plaintext JWS is a JWT with a String (non-JSON) body (payload) that has been
|
||||
* cryptographically signed.</p>
|
||||
*
|
||||
* <p><b>If the compact string presented does not reflect a plaintext JWS, an {@link UnsupportedJwtException}
|
||||
* will be thrown.</b></p>
|
||||
*
|
||||
* @param plaintextJws a compact serialized JWS string.
|
||||
* @return the {@link Jws Jws} instance that reflects the specified compact JWS string.
|
||||
* @throws UnsupportedJwtException if the {@code plaintextJws} argument does not represent an plaintext JWS
|
||||
* @throws MalformedJwtException if the {@code plaintextJws} string is not a valid JWS
|
||||
* @throws SignatureException if the {@code plaintextJws} JWS signature validation fails
|
||||
* @throws IllegalArgumentException if the {@code plaintextJws} string is {@code null} or empty or only whitespace
|
||||
* @see #parsePlaintextJwt(String)
|
||||
* @see #parseClaimsJwt(String)
|
||||
* @see #parseClaimsJws(String)
|
||||
* @see #parse(String, JwtHandler)
|
||||
* @see #parse(String)
|
||||
* @since 0.2
|
||||
*/
|
||||
Jws<String> parsePlaintextJws(String plaintextJws)
|
||||
throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Parses the specified compact serialized JWS string based on the builder's current configuration state and
|
||||
* returns
|
||||
* the resulting Claims JWS instance.
|
||||
*
|
||||
* <p>This is a convenience method that is usable if you are confident that the compact string argument reflects a
|
||||
* Claims JWS. A Claims JWS is a JWT with a {@link Claims} body that has been cryptographically signed.</p>
|
||||
*
|
||||
* <p><b>If the compact string presented does not reflect a Claims JWS, an {@link UnsupportedJwtException} will be
|
||||
* thrown.</b></p>
|
||||
*
|
||||
* @param claimsJws a compact serialized Claims JWS string.
|
||||
* @return the {@link Jws Jws} instance that reflects the specified compact Claims JWS string.
|
||||
* @throws UnsupportedJwtException if the {@code claimsJws} argument does not represent an Claims JWS
|
||||
* @throws MalformedJwtException if the {@code claimsJws} string is not a valid JWS
|
||||
* @throws SignatureException if the {@code claimsJws} JWS signature validation fails
|
||||
* @throws IllegalArgumentException if the {@code claimsJws} string is {@code null} or empty or only whitespace
|
||||
* @see #parsePlaintextJwt(String)
|
||||
* @see #parseClaimsJwt(String)
|
||||
* @see #parsePlaintextJws(String)
|
||||
* @see #parse(String, JwtHandler)
|
||||
* @see #parse(String)
|
||||
* @since 0.2
|
||||
*/
|
||||
Jws<Claims> parseClaimsJws(String claimsJws)
|
||||
throws UnsupportedJwtException, MalformedJwtException, SignatureException, IllegalArgumentException;
|
||||
}
|
||||
|
@ -91,9 +91,6 @@ public class Jwts {
|
||||
* @return a new {@link Claims} instance populated with the specified name/value pairs.
|
||||
*/
|
||||
public static Claims claims(Map<String, Object> claims) {
|
||||
if (claims == null) {
|
||||
return claims();
|
||||
}
|
||||
return new DefaultClaims(claims);
|
||||
}
|
||||
|
||||
|
@ -13,22 +13,24 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.jsonwebtoken.impl.crypto;
|
||||
package io.jsonwebtoken;
|
||||
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
/**
|
||||
* Exception thrown when receiving a JWT in a particular format/configuration that does not match the format expected
|
||||
* by the application.
|
||||
*
|
||||
* <p>For example, this exception would be thrown if parsing an unsigned plaintext JWT when the application
|
||||
* requires a cryptographically signed Claims JWS instead.</p>
|
||||
*
|
||||
* @since 0.2
|
||||
*/
|
||||
public class UnsupportedJwtException extends JwtException {
|
||||
|
||||
import java.security.Key;
|
||||
public UnsupportedJwtException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public abstract class AbstractSigner implements Signer {
|
||||
|
||||
protected final SignatureAlgorithm alg;
|
||||
protected final Key key;
|
||||
|
||||
protected AbstractSigner(SignatureAlgorithm alg, Key key) {
|
||||
Assert.notNull(alg, "SignatureAlgorithm cannot be null.");
|
||||
Assert.notNull(key, "Key cannot be null.");
|
||||
this.alg = alg;
|
||||
this.key = key;
|
||||
public UnsupportedJwtException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -18,12 +18,16 @@ package io.jsonwebtoken.impl;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Header;
|
||||
import io.jsonwebtoken.Jws;
|
||||
import io.jsonwebtoken.Jwt;
|
||||
import io.jsonwebtoken.JwsHeader;
|
||||
import io.jsonwebtoken.JwtHandler;
|
||||
import io.jsonwebtoken.JwtHandlerAdapter;
|
||||
import io.jsonwebtoken.JwtParser;
|
||||
import io.jsonwebtoken.MalformedJwtException;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.SignatureException;
|
||||
import io.jsonwebtoken.UnsupportedJwtException;
|
||||
import io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator;
|
||||
import io.jsonwebtoken.impl.crypto.JwtSignatureValidator;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
@ -218,6 +222,79 @@ public class DefaultJwtParser implements JwtParser {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T parse(String compact, JwtHandler<T> handler) throws MalformedJwtException, SignatureException {
|
||||
Assert.notNull(handler, "JwtHandler argument cannot be null.");
|
||||
Assert.hasText(compact, "JWT String argument cannot be null or empty.");
|
||||
|
||||
Jwt jwt = parse(compact);
|
||||
|
||||
if (jwt instanceof Jws) {
|
||||
Jws jws = (Jws)jwt;
|
||||
Object body = jws.getBody();
|
||||
if (body instanceof Claims) {
|
||||
return handler.onClaimsJws((Jws<Claims>)jws);
|
||||
} else {
|
||||
return handler.onPlaintextJws((Jws<String>)jws);
|
||||
}
|
||||
} else {
|
||||
Object body = jwt.getBody();
|
||||
if (body instanceof Claims) {
|
||||
return handler.onClaimsJwt((Jwt<Header, Claims>) jwt);
|
||||
} else {
|
||||
return handler.onPlaintextJwt((Jwt<Header, String>) jwt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jwt<Header, String> parsePlaintextJwt(String plaintextJwt) {
|
||||
return parse(plaintextJwt, new JwtHandlerAdapter<Jwt<Header, String>>() {
|
||||
@Override
|
||||
public Jwt<Header, String> onPlaintextJwt(Jwt<Header, String> jwt) {
|
||||
return jwt;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jwt<Header, Claims> parseClaimsJwt(String claimsJwt) {
|
||||
try {
|
||||
return parse(claimsJwt, new JwtHandlerAdapter<Jwt<Header, Claims>>() {
|
||||
@Override
|
||||
public Jwt<Header, Claims> onClaimsJwt(Jwt<Header, Claims> jwt) {
|
||||
return jwt;
|
||||
}
|
||||
});
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new UnsupportedJwtException("Signed JWSs are not supported.", iae);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jws<String> parsePlaintextJws(String plaintextJws) {
|
||||
try {
|
||||
return parse(plaintextJws, new JwtHandlerAdapter<Jws<String>>() {
|
||||
@Override
|
||||
public Jws<String> onPlaintextJws(Jws<String> jws) {
|
||||
return jws;
|
||||
}
|
||||
});
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new UnsupportedJwtException("Signed JWSs are not supported.", iae);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jws<Claims> parseClaimsJws(String claimsJws) {
|
||||
return parse(claimsJws, new JwtHandlerAdapter<Jws<Claims>>() {
|
||||
@Override
|
||||
public Jws<Claims> onClaimsJws(Jws<Claims> jws) {
|
||||
return jws;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map<String, Object> readValue(String val) {
|
||||
try {
|
||||
|
67
src/test/groovy/io/jsonwebtoken/JwtHandlerAdapterTest.groovy
Normal file
67
src/test/groovy/io/jsonwebtoken/JwtHandlerAdapterTest.groovy
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 org.testng.annotations.Test
|
||||
|
||||
import static org.testng.Assert.*
|
||||
|
||||
class JwtHandlerAdapterTest {
|
||||
|
||||
@Test
|
||||
void testOnPlaintextJwt() {
|
||||
def handler = new JwtHandlerAdapter();
|
||||
try {
|
||||
handler.onPlaintextJwt(null)
|
||||
fail()
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Unsigned plaintext JWTs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOnClaimsJwt() {
|
||||
def handler = new JwtHandlerAdapter();
|
||||
try {
|
||||
handler.onClaimsJwt(null)
|
||||
fail()
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Unsigned Claims JWTs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOnPlaintextJws() {
|
||||
def handler = new JwtHandlerAdapter();
|
||||
try {
|
||||
handler.onPlaintextJws(null)
|
||||
fail()
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Signed plaintext JWSs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOnClaimsJws() {
|
||||
def handler = new JwtHandlerAdapter();
|
||||
try {
|
||||
handler.onClaimsJws(null)
|
||||
fail()
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Signed Claims JWSs are not supported.'
|
||||
}
|
||||
}
|
||||
}
|
410
src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy
Normal file
410
src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy
Normal file
@ -0,0 +1,410 @@
|
||||
/*
|
||||
* 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.TextCodec
|
||||
import org.testng.annotations.Test
|
||||
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
import java.security.SecureRandom
|
||||
|
||||
import static org.testng.Assert.*
|
||||
|
||||
|
||||
class JwtParserTest {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetDuplicateSigningKeys() {
|
||||
|
||||
byte[] keyBytes = randomKey();
|
||||
|
||||
SecretKeySpec key = new SecretKeySpec(keyBytes, "HmacSHA256");
|
||||
|
||||
String compact = Jwts.builder().setPayload('Hello World!').signWith(SignatureAlgorithm.HS256, keyBytes).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().setSigningKey(keyBytes).setSigningKey(key).parse(compact)
|
||||
fail()
|
||||
} catch (IllegalStateException ise) {
|
||||
assertEquals ise.getMessage(), 'A key object and key bytes cannot both be specified. Choose either.'
|
||||
}
|
||||
}
|
||||
|
||||
@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 = TextCodec.BASE64.encode('{"alg":"none"}') + '.' +
|
||||
TextCodec.BASE64.encode(junkPayload) + '.';
|
||||
|
||||
try {
|
||||
Jwts.parser().parse(bad);
|
||||
fail()
|
||||
} catch (MalformedJwtException expected) {
|
||||
assertEquals expected.getMessage(), 'Unable to read JSON value: ' + junkPayload
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseJwsWithBadAlgHeader() {
|
||||
|
||||
String badAlgorithmName = 'whatever'
|
||||
|
||||
String header = "{\"alg\":\"$badAlgorithmName\"}";
|
||||
|
||||
String payload = '{"subject":"Joe"}'
|
||||
|
||||
String badSig = ";aklsjdf;kajsd;fkjas;dklfj"
|
||||
|
||||
String bad = TextCodec.BASE64.encode(header) + '.' +
|
||||
TextCodec.BASE64.encode(payload) + '.' +
|
||||
TextCodec.BASE64.encode(badSig);
|
||||
|
||||
try {
|
||||
Jwts.parser().setSigningKey(randomKey()).parse(bad);
|
||||
fail()
|
||||
} catch (SignatureException se) {
|
||||
assertEquals se.getMessage(), "Unsupported signature algorithm '$badAlgorithmName'"
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseWithInvalidSignature() {
|
||||
|
||||
String header = '{"alg":"HS256"}'
|
||||
|
||||
String payload = '{"subject":"Joe"}'
|
||||
|
||||
String badSig = ";aklsjdf;kajsd;fkjas;dklfj"
|
||||
|
||||
String bad = TextCodec.BASE64.encode(header) + '.' +
|
||||
TextCodec.BASE64.encode(payload) + '.' +
|
||||
TextCodec.BASE64.encode(badSig);
|
||||
|
||||
try {
|
||||
Jwts.parser().setSigningKey(randomKey()).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 testParsePlaintextJwsWithIncorrectAlg() {
|
||||
|
||||
String header = '{"alg":"none"}'
|
||||
|
||||
String payload = '{"subject":"Joe"}'
|
||||
|
||||
String badSig = ";aklsjdf;kajsd;fkjas;dklfj"
|
||||
|
||||
String bad = TextCodec.BASE64.encode(header) + '.' +
|
||||
TextCodec.BASE64.encode(payload) + '.' +
|
||||
TextCodec.BASE64.encode(badSig);
|
||||
|
||||
try {
|
||||
Jwts.parser().setSigningKey(randomKey()).parse(bad);
|
||||
fail()
|
||||
} catch (MalformedJwtException se) {
|
||||
assertEquals se.getMessage(), 'JWT string has a digest/signature, but the header does not reference a valid signature algorithm.'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseWithBase64EncodedSigningKey() {
|
||||
byte[] key = randomKey();
|
||||
String base64Encodedkey = TextCodec.BASE64.encode(key);
|
||||
String payload = 'Hello world!'
|
||||
|
||||
String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, base64Encodedkey).compact()
|
||||
|
||||
assertTrue Jwts.parser().isSigned(compact)
|
||||
|
||||
Jwt<Header,String> jwt = Jwts.parser().setSigningKey(base64Encodedkey).parse(compact)
|
||||
|
||||
assertEquals jwt.body, payload
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// parsePlaintextJwt tests
|
||||
// ========================================================================
|
||||
|
||||
@Test
|
||||
void testParsePlaintextJwt() {
|
||||
|
||||
String payload = 'Hello world!'
|
||||
|
||||
String compact = Jwts.builder().setPayload(payload).compact()
|
||||
|
||||
Jwt<Header,String> jwt = Jwts.parser().parsePlaintextJwt(compact);
|
||||
|
||||
assertEquals jwt.getBody(), payload
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParsePlaintextJwtWithClaimsJwt() {
|
||||
|
||||
String compact = Jwts.builder().setSubject('Joe').compact();
|
||||
|
||||
try {
|
||||
Jwts.parser().parsePlaintextJwt(compact);
|
||||
fail();
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Unsigned Claims JWTs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParsePlaintextJwtWithPlaintextJws() {
|
||||
|
||||
String payload = 'Hello world!'
|
||||
|
||||
String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, randomKey()).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().parsePlaintextJws(compact);
|
||||
fail();
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Signed JWSs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParsePlaintextJwtWithClaimsJws() {
|
||||
|
||||
String compact = Jwts.builder().setSubject('Joe').signWith(SignatureAlgorithm.HS256, randomKey()).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().parsePlaintextJws(compact);
|
||||
fail();
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Signed JWSs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// parseClaimsJwt tests
|
||||
// ========================================================================
|
||||
|
||||
@Test
|
||||
void testParseClaimsJwt() {
|
||||
|
||||
String subject = 'Joe'
|
||||
|
||||
String compact = Jwts.builder().setSubject(subject).compact()
|
||||
|
||||
Jwt<Header,Claims> jwt = Jwts.parser().parseClaimsJwt(compact);
|
||||
|
||||
assertEquals jwt.getBody().getSubject(), subject
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseClaimsJwtWithPlaintextJwt() {
|
||||
|
||||
String payload = 'Hello world!'
|
||||
|
||||
String compact = Jwts.builder().setPayload(payload).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().parseClaimsJwt(compact);
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Unsigned plaintext JWTs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseClaimsJwtWithPlaintextJws() {
|
||||
|
||||
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 e.getMessage(), 'Signed JWSs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseClaimsJwtWithClaimsJws() {
|
||||
|
||||
String compact = Jwts.builder().setSubject('Joe').signWith(SignatureAlgorithm.HS256, randomKey()).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().parseClaimsJwt(compact);
|
||||
fail();
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Signed JWSs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// parsePlaintextJws tests
|
||||
// ========================================================================
|
||||
|
||||
@Test
|
||||
void testParsePlaintextJws() {
|
||||
|
||||
String payload = 'Hello world!'
|
||||
|
||||
byte[] key = randomKey()
|
||||
|
||||
String compact = Jwts.builder().setPayload(payload).signWith(SignatureAlgorithm.HS256, key).compact()
|
||||
|
||||
Jwt<Header,String> jwt = Jwts.parser().setSigningKey(key).parsePlaintextJws(compact);
|
||||
|
||||
assertEquals jwt.getBody(), payload
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParsePlaintextJwsWithPlaintextJwt() {
|
||||
|
||||
String payload = 'Hello world!'
|
||||
|
||||
byte[] key = randomKey()
|
||||
|
||||
String compact = Jwts.builder().setPayload(payload).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().setSigningKey(key).parsePlaintextJws(compact);
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Unsigned plaintext JWTs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParsePlaintextJwsWithClaimsJwt() {
|
||||
|
||||
String subject = 'Joe'
|
||||
|
||||
byte[] key = randomKey()
|
||||
|
||||
String compact = Jwts.builder().setSubject(subject).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().setSigningKey(key).parsePlaintextJws(compact);
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Unsigned Claims JWTs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParsePlaintextJwsWithClaimsJws() {
|
||||
|
||||
String subject = 'Joe'
|
||||
|
||||
byte[] key = randomKey()
|
||||
|
||||
String compact = Jwts.builder().setSubject(subject).signWith(SignatureAlgorithm.HS256, key).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().setSigningKey(key).parsePlaintextJws(compact);
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Signed Claims JWSs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// parseClaimsJws tests
|
||||
// ========================================================================
|
||||
|
||||
@Test
|
||||
void testParseClaimsJws() {
|
||||
|
||||
String sub = 'Joe'
|
||||
|
||||
byte[] key = randomKey()
|
||||
|
||||
String compact = Jwts.builder().setSubject(sub).signWith(SignatureAlgorithm.HS256, key).compact()
|
||||
|
||||
Jwt<Header,Claims> jwt = Jwts.parser().setSigningKey(key).parseClaimsJws(compact);
|
||||
|
||||
assertEquals jwt.getBody().getSubject(), sub
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseClaimsJwsWithPlaintextJwt() {
|
||||
|
||||
String payload = 'Hello world!'
|
||||
|
||||
byte[] key = randomKey()
|
||||
|
||||
String compact = Jwts.builder().setPayload(payload).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().setSigningKey(key).parseClaimsJws(compact);
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Unsigned plaintext JWTs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseClaimsJwsWithClaimsJwt() {
|
||||
|
||||
String subject = 'Joe'
|
||||
|
||||
byte[] key = randomKey()
|
||||
|
||||
String compact = Jwts.builder().setSubject(subject).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().setSigningKey(key).parseClaimsJws(compact);
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Unsigned Claims JWTs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseClaimsJwsWithPlaintextJws() {
|
||||
|
||||
String subject = 'Joe'
|
||||
|
||||
byte[] key = randomKey()
|
||||
|
||||
String compact = Jwts.builder().setSubject(subject).signWith(SignatureAlgorithm.HS256, key).compact()
|
||||
|
||||
try {
|
||||
Jwts.parser().setSigningKey(key).parseClaimsJws(compact);
|
||||
} catch (UnsupportedJwtException e) {
|
||||
assertEquals e.getMessage(), 'Signed Claims JWSs are not supported.'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package io.jsonwebtoken
|
||||
|
||||
import io.jsonwebtoken.impl.DefaultHeader
|
||||
import io.jsonwebtoken.impl.DefaultJwsHeader
|
||||
import org.testng.annotations.Test
|
||||
|
||||
import java.security.KeyPair
|
||||
@ -27,6 +29,45 @@ import static org.testng.Assert.*
|
||||
|
||||
class JwtsTest {
|
||||
|
||||
@Test
|
||||
void testHeaderWithNoArgs() {
|
||||
def header = Jwts.header()
|
||||
assertTrue header instanceof DefaultHeader
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHeaderWithMapArg() {
|
||||
def header = Jwts.header([alg: "HS256"])
|
||||
assertTrue header instanceof DefaultHeader
|
||||
assertEquals header.alg, 'HS256'
|
||||
}
|
||||
|
||||
@Test
|
||||
void testJwsHeaderWithNoArgs() {
|
||||
def header = Jwts.jwsHeader()
|
||||
assertTrue header instanceof DefaultJwsHeader
|
||||
}
|
||||
|
||||
@Test
|
||||
void testJwsHeaderWithMapArg() {
|
||||
def header = Jwts.jwsHeader([alg: "HS256"])
|
||||
assertTrue header instanceof DefaultJwsHeader
|
||||
assertEquals header.getAlgorithm(), 'HS256'
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClaims() {
|
||||
Claims claims = Jwts.claims()
|
||||
assertNotNull claims
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClaimsWithMapArg() {
|
||||
Claims claims = Jwts.claims([sub: 'Joe'])
|
||||
assertNotNull claims
|
||||
assertEquals claims.getSubject(), 'Joe'
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPlaintextJwtString() {
|
||||
|
||||
@ -179,11 +220,11 @@ class JwtsTest {
|
||||
assertNull claims.getAudience()
|
||||
}
|
||||
|
||||
private Date dateWithOnlySecondPrecision() {
|
||||
private static Date dateWithOnlySecondPrecision() {
|
||||
return dateWithOnlySecondPrecision(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
private Date dateWithOnlySecondPrecision(long millis) {
|
||||
private static Date dateWithOnlySecondPrecision(long millis) {
|
||||
long seconds = millis / 1000;
|
||||
long secondOnlyPrecisionMillis = seconds * 1000;
|
||||
return new Date(secondOnlyPrecisionMillis);
|
||||
|
Loading…
x
Reference in New Issue
Block a user