remove redundent stubs

This commit is contained in:
am0o0
2024-07-13 18:06:02 +02:00
parent 71e1d63953
commit bf506f8a9e
99 changed files with 0 additions and 5524 deletions

View File

@@ -1,29 +0,0 @@
package com.auth0.jwt;
/**
* Contains constants representing the JWT header parameter names.
*/
public final class HeaderParams {
private HeaderParams() {}
/**
* The algorithm used to sign a JWT.
*/
public static final String ALGORITHM = "alg";
/**
* The content type of the JWT.
*/
public static final String CONTENT_TYPE = "cty";
/**
* The media type of the JWT.
*/
public static final String TYPE = "typ";
/**
* The key ID of a JWT used to specify the key for signature validation.
*/
public static final String KEY_ID = "kid";
}

View File

@@ -1,74 +0,0 @@
package com.auth0.jwt;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.impl.JWTParser;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.Verification;
/**
* Exposes all the JWT functionalities.
*/
@SuppressWarnings("WeakerAccess")
public class JWT {
private final JWTParser parser;
/**
* Constructs a new instance of the JWT library. Use this if you need to decode many JWT
* tokens on the fly and do not wish to instantiate a new parser for each invocation.
*/
public JWT() {
parser = new JWTParser();
}
/**
* Decode a given Json Web Token.
* <p>
* Note that this method <b>doesn't verify the token's signature!</b>
* Use it only if you trust the token or if you have already verified it.
*
* @param token with jwt format as string.
* @return a decoded JWT.
* @throws JWTDecodeException if any part of the token contained an invalid jwt
* or JSON format of each of the jwt parts.
*/
public DecodedJWT decodeJwt(String token) throws JWTDecodeException {
return new JWTDecoder(parser, token);
}
/**
* Decode a given Json Web Token.
* <p>
* Note that this method <b>doesn't verify the token's signature!</b>
* Use it only if you trust the token or if you have already verified it.
*
* @param token with jwt format as string.
* @return a decoded JWT.
* @throws JWTDecodeException if any part of the token contained an invalid jwt
* or JSON format of each of the jwt parts.
*/
public static DecodedJWT decode(String token) throws JWTDecodeException {
return new JWTDecoder(token);
}
/**
* Returns a {@link Verification} builder with the algorithm to be used to validate token signature.
*
* @param algorithm that will be used to verify the token's signature.
* @return {@link Verification} builder
* @throws IllegalArgumentException if the provided algorithm is null.
*/
public static Verification require(Algorithm algorithm) {
return JWTVerifier.init(algorithm);
}
/**
* Returns a Json Web Token builder used to create and sign tokens.
*
* @return a token builder.
*/
public static JWTCreator.Builder create() {
return JWTCreator.init();
}
}

View File

@@ -1,631 +0,0 @@
package com.auth0.jwt;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.SignatureGenerationException;
import com.auth0.jwt.impl.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.*;
import java.util.Map.Entry;
/**
* The JWTCreator class holds the sign method to generate a complete JWT (with Signature)
* from a given Header and Payload content.
* <p>
* This class is thread-safe.
*/
@SuppressWarnings("WeakerAccess")
public final class JWTCreator {
private final Algorithm algorithm;
private final String headerJson;
private final String payloadJson;
private static final ObjectMapper mapper;
private static final SimpleModule module;
static {
module = new SimpleModule();
module.addSerializer(PayloadClaimsHolder.class, new PayloadSerializer());
module.addSerializer(HeaderClaimsHolder.class, new HeaderSerializer());
mapper = JsonMapper.builder()
.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
.build()
.registerModule(module);
}
private JWTCreator(Algorithm algorithm, Map<String, Object> headerClaims, Map<String, Object> payloadClaims)
throws JWTCreationException {
this.algorithm = algorithm;
try {
headerJson = mapper.writeValueAsString(new HeaderClaimsHolder(headerClaims));
payloadJson = mapper.writeValueAsString(new PayloadClaimsHolder(payloadClaims));
} catch (JsonProcessingException e) {
throw new JWTCreationException("Some of the Claims couldn't be converted to a valid JSON format.", e);
}
}
/**
* Initialize a JWTCreator instance.
*
* @return a JWTCreator.Builder instance to configure.
*/
static JWTCreator.Builder init() {
return new Builder();
}
/**
* The Builder class holds the Claims that defines the JWT to be created.
*/
public static class Builder {
private final Map<String, Object> payloadClaims;
private final Map<String, Object> headerClaims;
Builder() {
this.payloadClaims = new LinkedHashMap<>();
this.headerClaims = new LinkedHashMap<>();
}
/**
* Add specific Claims to set as the Header.
* If provided map is null then nothing is changed
*
* @param headerClaims the values to use as Claims in the token's Header.
* @return this same Builder instance.
*/
public Builder withHeader(Map<String, Object> headerClaims) {
if (headerClaims == null) {
return this;
}
for (Map.Entry<String, Object> entry : headerClaims.entrySet()) {
if (entry.getValue() == null) {
this.headerClaims.remove(entry.getKey());
} else {
this.headerClaims.put(entry.getKey(), entry.getValue());
}
}
return this;
}
/**
* Add specific Claims to set as the Header.
* If provided json is null then nothing is changed
*
* @param headerClaimsJson the values to use as Claims in the token's Header.
* @return this same Builder instance.
* @throws IllegalArgumentException if json value has invalid structure
*/
public Builder withHeader(String headerClaimsJson) throws IllegalArgumentException {
if (headerClaimsJson == null) {
return this;
}
try {
Map<String, Object> headerClaims = mapper.readValue(headerClaimsJson, LinkedHashMap.class);
return withHeader(headerClaims);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Invalid header JSON", e);
}
}
/**
* Add a specific Key Id ("kid") claim to the Header.
* If the {@link Algorithm} used to sign this token was instantiated with a KeyProvider,
* the 'kid' value will be taken from that provider and this one will be ignored.
*
* @param keyId the Key Id value.
* @return this same Builder instance.
*/
public Builder withKeyId(String keyId) {
this.headerClaims.put(HeaderParams.KEY_ID, keyId);
return this;
}
/**
* Add a specific Issuer ("iss") claim to the Payload.
*
* @param issuer the Issuer value.
* @return this same Builder instance.
*/
public Builder withIssuer(String issuer) {
addClaim(RegisteredClaims.ISSUER, issuer);
return this;
}
/**
* Add a specific Subject ("sub") claim to the Payload.
*
* @param subject the Subject value.
* @return this same Builder instance.
*/
public Builder withSubject(String subject) {
addClaim(RegisteredClaims.SUBJECT, subject);
return this;
}
/**
* Add a specific Audience ("aud") claim to the Payload.
*
* @param audience the Audience value.
* @return this same Builder instance.
*/
public Builder withAudience(String... audience) {
addClaim(RegisteredClaims.AUDIENCE, audience);
return this;
}
/**
* Add a specific Expires At ("exp") claim to the payload. The claim will be written as seconds since the epoch.
* Milliseconds will be truncated by rounding down to the nearest second.
*
* @param expiresAt the Expires At value.
* @return this same Builder instance.
*/
public Builder withExpiresAt(Date expiresAt) {
addClaim(RegisteredClaims.EXPIRES_AT, expiresAt);
return this;
}
/**
* Add a specific Expires At ("exp") claim to the payload. The claim will be written as seconds since the epoch;
* Milliseconds will be truncated by rounding down to the nearest second.
*
* @param expiresAt the Expires At value.
* @return this same Builder instance.
*/
public Builder withExpiresAt(Instant expiresAt) {
addClaim(RegisteredClaims.EXPIRES_AT, expiresAt);
return this;
}
/**
* Add a specific Not Before ("nbf") claim to the Payload. The claim will be written as seconds since the epoch;
* Milliseconds will be truncated by rounding down to the nearest second.
*
* @param notBefore the Not Before value.
* @return this same Builder instance.
*/
public Builder withNotBefore(Date notBefore) {
addClaim(RegisteredClaims.NOT_BEFORE, notBefore);
return this;
}
/**
* Add a specific Not Before ("nbf") claim to the Payload. The claim will be written as seconds since the epoch;
* Milliseconds will be truncated by rounding down to the nearest second.
*
* @param notBefore the Not Before value.
* @return this same Builder instance.
*/
public Builder withNotBefore(Instant notBefore) {
addClaim(RegisteredClaims.NOT_BEFORE, notBefore);
return this;
}
/**
* Add a specific Issued At ("iat") claim to the Payload. The claim will be written as seconds since the epoch;
* Milliseconds will be truncated by rounding down to the nearest second.
*
* @param issuedAt the Issued At value.
* @return this same Builder instance.
*/
public Builder withIssuedAt(Date issuedAt) {
addClaim(RegisteredClaims.ISSUED_AT, issuedAt);
return this;
}
/**
* Add a specific Issued At ("iat") claim to the Payload. The claim will be written as seconds since the epoch;
* Milliseconds will be truncated by rounding down to the nearest second.
*
* @param issuedAt the Issued At value.
* @return this same Builder instance.
*/
public Builder withIssuedAt(Instant issuedAt) {
addClaim(RegisteredClaims.ISSUED_AT, issuedAt);
return this;
}
/**
* Add a specific JWT Id ("jti") claim to the Payload.
*
* @param jwtId the Token Id value.
* @return this same Builder instance.
*/
public Builder withJWTId(String jwtId) {
addClaim(RegisteredClaims.JWT_ID, jwtId);
return this;
}
/**
* Add a custom Claim value.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null.
*/
public Builder withClaim(String name, Boolean value) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, value);
return this;
}
/**
* Add a custom Claim value.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null.
*/
public Builder withClaim(String name, Integer value) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, value);
return this;
}
/**
* Add a custom Claim value.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null.
*/
public Builder withClaim(String name, Long value) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, value);
return this;
}
/**
* Add a custom Claim value.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null.
*/
public Builder withClaim(String name, Double value) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, value);
return this;
}
/**
* Add a custom Claim value.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null.
*/
public Builder withClaim(String name, String value) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, value);
return this;
}
/**
* Add a custom Claim value. The claim will be written as seconds since the epoch.
* Milliseconds will be truncated by rounding down to the nearest second.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null.
*/
public Builder withClaim(String name, Date value) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, value);
return this;
}
/**
* Add a custom Claim value. The claim will be written as seconds since the epoch.
* Milliseconds will be truncated by rounding down to the nearest second.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null.
*/
public Builder withClaim(String name, Instant value) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, value);
return this;
}
/**
* Add a custom Map Claim with the given items.
* <p>
* Accepted nested types are {@linkplain Map} and {@linkplain List} with basic types
* {@linkplain Boolean}, {@linkplain Integer}, {@linkplain Long}, {@linkplain Double},
* {@linkplain String} and {@linkplain Date}. {@linkplain Map}s cannot contain null keys or values.
* {@linkplain List}s can contain null elements.
*
* @param name the Claim's name.
* @param map the Claim's key-values.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null, or if the map contents does not validate.
*/
public Builder withClaim(String name, Map<String, ?> map) throws IllegalArgumentException {
assertNonNull(name);
// validate map contents
if (map != null && !validateClaim(map)) {
throw new IllegalArgumentException("Expected map containing Map, List, Boolean, Integer, "
+ "Long, Double, String and Date");
}
addClaim(name, map);
return this;
}
/**
* Add a custom List Claim with the given items.
* <p>
* Accepted nested types are {@linkplain Map} and {@linkplain List} with basic types
* {@linkplain Boolean}, {@linkplain Integer}, {@linkplain Long}, {@linkplain Double},
* {@linkplain String} and {@linkplain Date}. {@linkplain Map}s cannot contain null keys or values.
* {@linkplain List}s can contain null elements.
*
* @param name the Claim's name.
* @param list the Claim's list of values.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null, or if the list contents does not validate.
*/
public Builder withClaim(String name, List<?> list) throws IllegalArgumentException {
assertNonNull(name);
// validate list contents
if (list != null && !validateClaim(list)) {
throw new IllegalArgumentException("Expected list containing Map, List, Boolean, Integer, "
+ "Long, Double, String and Date");
}
addClaim(name, list);
return this;
}
/**
* Add a custom claim with null value.
*
* @param name the Claim's name.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null
*/
public Builder withNullClaim(String name) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, null);
return this;
}
/**
* Add a custom Array Claim with the given items.
*
* @param name the Claim's name.
* @param items the Claim's value.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null.
*/
public Builder withArrayClaim(String name, String[] items) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, items);
return this;
}
/**
* Add a custom Array Claim with the given items.
*
* @param name the Claim's name.
* @param items the Claim's value.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null.
*/
public Builder withArrayClaim(String name, Integer[] items) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, items);
return this;
}
/**
* Add a custom Array Claim with the given items.
*
* @param name the Claim's name.
* @param items the Claim's value.
* @return this same Builder instance.
* @throws IllegalArgumentException if the name is null
*/
public Builder withArrayClaim(String name, Long[] items) throws IllegalArgumentException {
assertNonNull(name);
addClaim(name, items);
return this;
}
/**
* Add specific Claims to set as the Payload. If the provided map is null then
* nothing is changed.
* <p>
* Accepted types are {@linkplain Map} and {@linkplain List} with basic types
* {@linkplain Boolean}, {@linkplain Integer}, {@linkplain Long}, {@linkplain Double},
* {@linkplain String} and {@linkplain Date}.
* {@linkplain Map}s and {@linkplain List}s can contain null elements.
* </p>
*
* <p>
* If any of the claims are invalid, none will be added.
* </p>
*
* @param payloadClaims the values to use as Claims in the token's payload.
* @return this same Builder instance.
* @throws IllegalArgumentException if any of the claim keys or null,
* or if the values are not of a supported type.
*/
public Builder withPayload(Map<String, ?> payloadClaims) throws IllegalArgumentException {
if (payloadClaims == null) {
return this;
}
if (!validatePayload(payloadClaims)) {
throw new IllegalArgumentException("Claim values must only be of types Map, List, Boolean, Integer, "
+ "Long, Double, String, Date, Instant, and Null");
}
// add claims only after validating all claims so as not to corrupt the claims map of this builder
for (Map.Entry<String, ?> entry : payloadClaims.entrySet()) {
addClaim(entry.getKey(), entry.getValue());
}
return this;
}
/**
* Add specific Claims to set as the Payload. If the provided json is null then
* nothing is changed.
*
* <p>
* If any of the claims are invalid, none will be added.
* </p>
*
* @param payloadClaimsJson the values to use as Claims in the token's payload.
* @return this same Builder instance.
* @throws IllegalArgumentException if any of the claim keys or null,
* or if the values are not of a supported type,
* or if json value has invalid structure.
*/
public Builder withPayload(String payloadClaimsJson) throws IllegalArgumentException {
if (payloadClaimsJson == null) {
return this;
}
try {
Map<String, Object> payloadClaims = mapper.readValue(payloadClaimsJson, LinkedHashMap.class);
return withPayload(payloadClaims);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Invalid payload JSON", e);
}
}
private boolean validatePayload(Map<String, ?> payload) {
for (Map.Entry<String, ?> entry : payload.entrySet()) {
String key = entry.getKey();
assertNonNull(key);
Object value = entry.getValue();
if (value instanceof List && !validateClaim((List<?>) value)) {
return false;
} else if (value instanceof Map && !validateClaim((Map<?, ?>) value)) {
return false;
} else if (!isSupportedType(value)) {
return false;
}
}
return true;
}
private static boolean validateClaim(Map<?, ?> map) {
// do not accept null values in maps
for (Entry<?, ?> entry : map.entrySet()) {
Object value = entry.getValue();
if (!isSupportedType(value)) {
return false;
}
if (!(entry.getKey() instanceof String)) {
return false;
}
}
return true;
}
private static boolean validateClaim(List<?> list) {
// accept null values in list
for (Object object : list) {
if (!isSupportedType(object)) {
return false;
}
}
return true;
}
private static boolean isSupportedType(Object value) {
if (value instanceof List) {
return validateClaim((List<?>) value);
} else if (value instanceof Map) {
return validateClaim((Map<?, ?>) value);
} else {
return isBasicType(value);
}
}
private static boolean isBasicType(Object value) {
if (value == null) {
return true;
} else {
Class<?> c = value.getClass();
if (c.isArray()) {
return c == Integer[].class || c == Long[].class || c == String[].class;
}
return c == String.class || c == Integer.class || c == Long.class || c == Double.class
|| c == Date.class || c == Instant.class || c == Boolean.class;
}
}
/**
* Creates a new JWT and signs is with the given algorithm.
*
* @param algorithm used to sign the JWT
* @return a new JWT token
* @throws IllegalArgumentException if the provided algorithm is null.
* @throws JWTCreationException if the claims could not be converted to a valid JSON
* or there was a problem with the signing key.
*/
public String sign(Algorithm algorithm) throws IllegalArgumentException, JWTCreationException {
if (algorithm == null) {
throw new IllegalArgumentException("The Algorithm cannot be null.");
}
headerClaims.put(HeaderParams.ALGORITHM, algorithm.getName());
if (!headerClaims.containsKey(HeaderParams.TYPE)) {
headerClaims.put(HeaderParams.TYPE, "JWT");
}
String signingKeyId = algorithm.getSigningKeyId();
if (signingKeyId != null) {
withKeyId(signingKeyId);
}
return new JWTCreator(algorithm, headerClaims, payloadClaims).sign();
}
private void assertNonNull(String name) {
if (name == null) {
throw new IllegalArgumentException("The Custom Claim's name can't be null.");
}
}
private void addClaim(String name, Object value) {
payloadClaims.put(name, value);
}
}
private String sign() throws SignatureGenerationException {
String header = Base64.getUrlEncoder().withoutPadding()
.encodeToString(headerJson.getBytes(StandardCharsets.UTF_8));
String payload = Base64.getUrlEncoder().withoutPadding()
.encodeToString(payloadJson.getBytes(StandardCharsets.UTF_8));
byte[] signatureBytes = algorithm.sign(header.getBytes(StandardCharsets.UTF_8),
payload.getBytes(StandardCharsets.UTF_8));
String signature = Base64.getUrlEncoder().withoutPadding().encodeToString((signatureBytes));
return String.format("%s.%s.%s", header, payload, signature);
}
}

View File

@@ -1,156 +0,0 @@
package com.auth0.jwt;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.impl.JWTParser;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.Header;
import com.auth0.jwt.interfaces.Payload;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* The JWTDecoder class holds the decode method to parse a given JWT token into it's JWT representation.
* <p>
* This class is thread-safe.
*/
@SuppressWarnings("WeakerAccess")
final class JWTDecoder implements DecodedJWT, Serializable {
private static final long serialVersionUID = 1873362438023312895L;
private final String[] parts;
private final Header header;
private final Payload payload;
JWTDecoder(String jwt) throws JWTDecodeException {
this(new JWTParser(), jwt);
}
JWTDecoder(JWTParser converter, String jwt) throws JWTDecodeException {
parts = TokenUtils.splitToken(jwt);
String headerJson;
String payloadJson;
try {
headerJson = new String(Base64.getUrlDecoder().decode(parts[0]), StandardCharsets.UTF_8);
payloadJson = new String(Base64.getUrlDecoder().decode(parts[1]), StandardCharsets.UTF_8);
} catch (NullPointerException e) {
throw new JWTDecodeException("The UTF-8 Charset isn't initialized.", e);
} catch (IllegalArgumentException e) {
throw new JWTDecodeException("The input is not a valid base 64 encoded string.", e);
}
header = converter.parseHeader(headerJson);
payload = converter.parsePayload(payloadJson);
}
@Override
public String getAlgorithm() {
return header.getAlgorithm();
}
@Override
public String getType() {
return header.getType();
}
@Override
public String getContentType() {
return header.getContentType();
}
@Override
public String getKeyId() {
return header.getKeyId();
}
@Override
public Claim getHeaderClaim(String name) {
return header.getHeaderClaim(name);
}
@Override
public String getIssuer() {
return payload.getIssuer();
}
@Override
public String getSubject() {
return payload.getSubject();
}
@Override
public List<String> getAudience() {
return payload.getAudience();
}
@Override
public Date getExpiresAt() {
return payload.getExpiresAt();
}
@Override
public Instant getExpiresAtAsInstant() {
return payload.getExpiresAtAsInstant();
}
@Override
public Date getNotBefore() {
return payload.getNotBefore();
}
@Override
public Instant getNotBeforeAsInstant() {
return payload.getNotBeforeAsInstant();
}
@Override
public Date getIssuedAt() {
return payload.getIssuedAt();
}
@Override
public Instant getIssuedAtAsInstant() {
return payload.getIssuedAtAsInstant();
}
@Override
public String getId() {
return payload.getId();
}
@Override
public Claim getClaim(String name) {
return payload.getClaim(name);
}
@Override
public Map<String, Claim> getClaims() {
return payload.getClaims();
}
@Override
public String getHeader() {
return parts[0];
}
@Override
public String getPayload() {
return parts[1];
}
@Override
public String getSignature() {
return parts[2];
}
@Override
public String getToken() {
return String.format("%s.%s.%s", parts[0], parts[1], parts[2]);
}
}

View File

@@ -1,493 +0,0 @@
package com.auth0.jwt;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.*;
import com.auth0.jwt.impl.JWTParser;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.impl.ExpectedCheckHolder;
import com.auth0.jwt.interfaces.Verification;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.function.BiPredicate;
/**
* The JWTVerifier class holds the verify method to assert that a given Token has not only a proper JWT format,
* but also its signature matches.
* <p>
* This class is thread-safe.
*
* @see com.auth0.jwt.interfaces.JWTVerifier
*/
public final class JWTVerifier implements com.auth0.jwt.interfaces.JWTVerifier {
private final Algorithm algorithm;
final List<ExpectedCheckHolder> expectedChecks;
private final JWTParser parser;
JWTVerifier(Algorithm algorithm, List<ExpectedCheckHolder> expectedChecks) {
this.algorithm = algorithm;
this.expectedChecks = Collections.unmodifiableList(expectedChecks);
this.parser = new JWTParser();
}
/**
* Initialize a {@link Verification} instance using the given Algorithm.
*
* @param algorithm the Algorithm to use on the JWT verification.
* @return a {@link Verification} instance to configure.
* @throws IllegalArgumentException if the provided algorithm is null.
*/
static Verification init(Algorithm algorithm) throws IllegalArgumentException {
return new BaseVerification(algorithm);
}
/**
* {@link Verification} implementation that accepts all the expected Claim values for verification, and
* builds a {@link com.auth0.jwt.interfaces.JWTVerifier} used to verify a JWT's signature and expected claims.
*
* Note that this class is <strong>not</strong> thread-safe. Calling {@link #build()} returns an instance of
* {@link com.auth0.jwt.interfaces.JWTVerifier} which can be reused.
*/
public static class BaseVerification implements Verification {
private final Algorithm algorithm;
private final List<ExpectedCheckHolder> expectedChecks;
private long defaultLeeway;
private final Map<String, Long> customLeeways;
private boolean ignoreIssuedAt;
private Clock clock;
BaseVerification(Algorithm algorithm) throws IllegalArgumentException {
if (algorithm == null) {
throw new IllegalArgumentException("The Algorithm cannot be null.");
}
this.algorithm = algorithm;
this.expectedChecks = new ArrayList<>();
this.customLeeways = new HashMap<>();
this.defaultLeeway = 0;
}
@Override
public Verification withIssuer(String... issuer) {
List<String> value = isNullOrEmpty(issuer) ? null : Arrays.asList(issuer);
addCheck(RegisteredClaims.ISSUER, ((claim, decodedJWT) -> {
if (verifyNull(claim, value)) {
return true;
}
if (value == null || !value.contains(claim.asString())) {
throw new IncorrectClaimException(
"The Claim 'iss' value doesn't match the required issuer.", RegisteredClaims.ISSUER, claim);
}
return true;
}));
return this;
}
@Override
public Verification withSubject(String subject) {
addCheck(RegisteredClaims.SUBJECT, (claim, decodedJWT) ->
verifyNull(claim, subject) || subject.equals(claim.asString()));
return this;
}
@Override
public Verification withAudience(String... audience) {
List<String> value = isNullOrEmpty(audience) ? null : Arrays.asList(audience);
addCheck(RegisteredClaims.AUDIENCE, ((claim, decodedJWT) -> {
if (verifyNull(claim, value)) {
return true;
}
if (!assertValidAudienceClaim(decodedJWT.getAudience(), value, true)) {
throw new IncorrectClaimException("The Claim 'aud' value doesn't contain the required audience.",
RegisteredClaims.AUDIENCE, claim);
}
return true;
}));
return this;
}
@Override
public Verification withAnyOfAudience(String... audience) {
List<String> value = isNullOrEmpty(audience) ? null : Arrays.asList(audience);
addCheck(RegisteredClaims.AUDIENCE, ((claim, decodedJWT) -> {
if (verifyNull(claim, value)) {
return true;
}
if (!assertValidAudienceClaim(decodedJWT.getAudience(), value, false)) {
throw new IncorrectClaimException("The Claim 'aud' value doesn't contain the required audience.",
RegisteredClaims.AUDIENCE, claim);
}
return true;
}));
return this;
}
@Override
public Verification acceptLeeway(long leeway) throws IllegalArgumentException {
assertPositive(leeway);
this.defaultLeeway = leeway;
return this;
}
@Override
public Verification acceptExpiresAt(long leeway) throws IllegalArgumentException {
assertPositive(leeway);
customLeeways.put(RegisteredClaims.EXPIRES_AT, leeway);
return this;
}
@Override
public Verification acceptNotBefore(long leeway) throws IllegalArgumentException {
assertPositive(leeway);
customLeeways.put(RegisteredClaims.NOT_BEFORE, leeway);
return this;
}
@Override
public Verification acceptIssuedAt(long leeway) throws IllegalArgumentException {
assertPositive(leeway);
customLeeways.put(RegisteredClaims.ISSUED_AT, leeway);
return this;
}
@Override
public Verification ignoreIssuedAt() {
this.ignoreIssuedAt = true;
return this;
}
@Override
public Verification withJWTId(String jwtId) {
addCheck(RegisteredClaims.JWT_ID, ((claim, decodedJWT) ->
verifyNull(claim, jwtId) || jwtId.equals(claim.asString())));
return this;
}
@Override
public Verification withClaimPresence(String name) throws IllegalArgumentException {
assertNonNull(name);
//since addCheck already checks presence, we just return true
withClaim(name, ((claim, decodedJWT) -> true));
return this;
}
@Override
public Verification withNullClaim(String name) throws IllegalArgumentException {
assertNonNull(name);
withClaim(name, ((claim, decodedJWT) -> claim.isNull()));
return this;
}
@Override
public Verification withClaim(String name, Boolean value) throws IllegalArgumentException {
assertNonNull(name);
addCheck(name, ((claim, decodedJWT) -> verifyNull(claim, value)
|| value.equals(claim.asBoolean())));
return this;
}
@Override
public Verification withClaim(String name, Integer value) throws IllegalArgumentException {
assertNonNull(name);
addCheck(name, ((claim, decodedJWT) -> verifyNull(claim, value)
|| value.equals(claim.asInt())));
return this;
}
@Override
public Verification withClaim(String name, Long value) throws IllegalArgumentException {
assertNonNull(name);
addCheck(name, ((claim, decodedJWT) -> verifyNull(claim, value)
|| value.equals(claim.asLong())));
return this;
}
@Override
public Verification withClaim(String name, Double value) throws IllegalArgumentException {
assertNonNull(name);
addCheck(name, ((claim, decodedJWT) -> verifyNull(claim, value)
|| value.equals(claim.asDouble())));
return this;
}
@Override
public Verification withClaim(String name, String value) throws IllegalArgumentException {
assertNonNull(name);
addCheck(name, ((claim, decodedJWT) -> verifyNull(claim, value)
|| value.equals(claim.asString())));
return this;
}
@Override
public Verification withClaim(String name, Date value) throws IllegalArgumentException {
return withClaim(name, value != null ? value.toInstant() : null);
}
@Override
public Verification withClaim(String name, Instant value) throws IllegalArgumentException {
assertNonNull(name);
// Since date-time claims are serialized as epoch seconds,
// we need to compare them with only seconds-granularity
addCheck(name,
((claim, decodedJWT) -> verifyNull(claim, value)
|| value.truncatedTo(ChronoUnit.SECONDS).equals(claim.asInstant())));
return this;
}
@Override
public Verification withClaim(String name, BiPredicate<Claim, DecodedJWT> predicate)
throws IllegalArgumentException {
assertNonNull(name);
addCheck(name, ((claim, decodedJWT) -> verifyNull(claim, predicate)
|| predicate.test(claim, decodedJWT)));
return this;
}
@Override
public Verification withArrayClaim(String name, String... items) throws IllegalArgumentException {
assertNonNull(name);
addCheck(name, ((claim, decodedJWT) -> verifyNull(claim, items)
|| assertValidCollectionClaim(claim, items)));
return this;
}
@Override
public Verification withArrayClaim(String name, Integer... items) throws IllegalArgumentException {
assertNonNull(name);
addCheck(name, ((claim, decodedJWT) -> verifyNull(claim, items)
|| assertValidCollectionClaim(claim, items)));
return this;
}
@Override
public Verification withArrayClaim(String name, Long... items) throws IllegalArgumentException {
assertNonNull(name);
addCheck(name, ((claim, decodedJWT) -> verifyNull(claim, items)
|| assertValidCollectionClaim(claim, items)));
return this;
}
@Override
public JWTVerifier build() {
return this.build(Clock.systemUTC());
}
/**
* Creates a new and reusable instance of the JWTVerifier with the configuration already provided.
* ONLY FOR TEST PURPOSES.
*
* @param clock the instance that will handle the current time.
* @return a new JWTVerifier instance with a custom {@link java.time.Clock}
*/
public JWTVerifier build(Clock clock) {
this.clock = clock;
addMandatoryClaimChecks();
return new JWTVerifier(algorithm, expectedChecks);
}
/**
* Fetches the Leeway set for claim or returns the {@link BaseVerification#defaultLeeway}.
*
* @param name Claim for which leeway is fetched
* @return Leeway value set for the claim
*/
public long getLeewayFor(String name) {
return customLeeways.getOrDefault(name, defaultLeeway);
}
private void addMandatoryClaimChecks() {
long expiresAtLeeway = getLeewayFor(RegisteredClaims.EXPIRES_AT);
long notBeforeLeeway = getLeewayFor(RegisteredClaims.NOT_BEFORE);
long issuedAtLeeway = getLeewayFor(RegisteredClaims.ISSUED_AT);
expectedChecks.add(constructExpectedCheck(RegisteredClaims.EXPIRES_AT, (claim, decodedJWT) ->
assertValidInstantClaim(RegisteredClaims.EXPIRES_AT, claim, expiresAtLeeway, true)));
expectedChecks.add(constructExpectedCheck(RegisteredClaims.NOT_BEFORE, (claim, decodedJWT) ->
assertValidInstantClaim(RegisteredClaims.NOT_BEFORE, claim, notBeforeLeeway, false)));
if (!ignoreIssuedAt) {
expectedChecks.add(constructExpectedCheck(RegisteredClaims.ISSUED_AT, (claim, decodedJWT) ->
assertValidInstantClaim(RegisteredClaims.ISSUED_AT, claim, issuedAtLeeway, false)));
}
}
private boolean assertValidCollectionClaim(Claim claim, Object[] expectedClaimValue) {
List<Object> claimArr;
Object[] claimAsObject = claim.as(Object[].class);
// Jackson uses 'natural' mapping which uses Integer if value fits in 32 bits.
if (expectedClaimValue instanceof Long[]) {
// convert Integers to Longs for comparison with equals
claimArr = new ArrayList<>(claimAsObject.length);
for (Object cao : claimAsObject) {
if (cao instanceof Integer) {
claimArr.add(((Integer) cao).longValue());
} else {
claimArr.add(cao);
}
}
} else {
claimArr = Arrays.asList(claim.as(Object[].class));
}
List<Object> valueArr = Arrays.asList(expectedClaimValue);
return claimArr.containsAll(valueArr);
}
private boolean assertValidInstantClaim(String claimName, Claim claim, long leeway, boolean shouldBeFuture) {
Instant claimVal = claim.asInstant();
Instant now = clock.instant().truncatedTo(ChronoUnit.SECONDS);
boolean isValid;
if (shouldBeFuture) {
isValid = assertInstantIsFuture(claimVal, leeway, now);
if (!isValid) {
throw new TokenExpiredException(String.format("The Token has expired on %s.", claimVal), claimVal);
}
} else {
isValid = assertInstantIsLessThanOrEqualToNow(claimVal, leeway, now);
if (!isValid) {
throw new IncorrectClaimException(
String.format("The Token can't be used before %s.", claimVal), claimName, claim);
}
}
return true;
}
private boolean assertInstantIsFuture(Instant claimVal, long leeway, Instant now) {
return claimVal == null || now.minus(Duration.ofSeconds(leeway)).isBefore(claimVal);
}
private boolean assertInstantIsLessThanOrEqualToNow(Instant claimVal, long leeway, Instant now) {
return !(claimVal != null && now.plus(Duration.ofSeconds(leeway)).isBefore(claimVal));
}
private boolean assertValidAudienceClaim(
List<String> audience,
List<String> values,
boolean shouldContainAll
) {
return !(audience == null || (shouldContainAll && !audience.containsAll(values))
|| (!shouldContainAll && Collections.disjoint(audience, values)));
}
private void assertPositive(long leeway) {
if (leeway < 0) {
throw new IllegalArgumentException("Leeway value can't be negative.");
}
}
private void assertNonNull(String name) {
if (name == null) {
throw new IllegalArgumentException("The Custom Claim's name can't be null.");
}
}
private void addCheck(String name, BiPredicate<Claim, DecodedJWT> predicate) {
expectedChecks.add(constructExpectedCheck(name, (claim, decodedJWT) -> {
if (claim.isMissing()) {
throw new MissingClaimException(name);
}
return predicate.test(claim, decodedJWT);
}));
}
private ExpectedCheckHolder constructExpectedCheck(String claimName, BiPredicate<Claim, DecodedJWT> check) {
return new ExpectedCheckHolder() {
@Override
public String getClaimName() {
return claimName;
}
@Override
public boolean verify(Claim claim, DecodedJWT decodedJWT) {
return check.test(claim, decodedJWT);
}
};
}
private boolean verifyNull(Claim claim, Object value) {
return value == null && claim.isNull();
}
private boolean isNullOrEmpty(String[] args) {
if (args == null || args.length == 0) {
return true;
}
boolean isAllNull = true;
for (String arg : args) {
if (arg != null) {
isAllNull = false;
break;
}
}
return isAllNull;
}
}
/**
* Perform the verification against the given Token, using any previous configured options.
*
* @param token to verify.
* @return a verified and decoded JWT.
* @throws AlgorithmMismatchException if the algorithm stated in the token's header is not equal to
* the one defined in the {@link JWTVerifier}.
* @throws SignatureVerificationException if the signature is invalid.
* @throws TokenExpiredException if the token has expired.
* @throws MissingClaimException if a claim to be verified is missing.
* @throws IncorrectClaimException if a claim contained a different value than the expected one.
*/
@Override
public DecodedJWT verify(String token) throws JWTVerificationException {
DecodedJWT jwt = new JWTDecoder(parser, token);
return verify(jwt);
}
/**
* Perform the verification against the given decoded JWT, using any previous configured options.
*
* @param jwt to verify.
* @return a verified and decoded JWT.
* @throws AlgorithmMismatchException if the algorithm stated in the token's header is not equal to
* the one defined in the {@link JWTVerifier}.
* @throws SignatureVerificationException if the signature is invalid.
* @throws TokenExpiredException if the token has expired.
* @throws MissingClaimException if a claim to be verified is missing.
* @throws IncorrectClaimException if a claim contained a different value than the expected one.
*/
@Override
public DecodedJWT verify(DecodedJWT jwt) throws JWTVerificationException {
verifyAlgorithm(jwt, algorithm);
algorithm.verify(jwt);
verifyClaims(jwt, expectedChecks);
return jwt;
}
private void verifyAlgorithm(DecodedJWT jwt, Algorithm expectedAlgorithm) throws AlgorithmMismatchException {
if (!expectedAlgorithm.getName().equals(jwt.getAlgorithm())) {
throw new AlgorithmMismatchException(
"The provided Algorithm doesn't match the one defined in the JWT's Header.");
}
}
private void verifyClaims(DecodedJWT jwt, List<ExpectedCheckHolder> expectedChecks)
throws TokenExpiredException, InvalidClaimException {
for (ExpectedCheckHolder expectedCheck : expectedChecks) {
boolean isValid;
String claimName = expectedCheck.getClaimName();
Claim claim = jwt.getClaim(claimName);
isValid = expectedCheck.verify(claim, jwt);
if (!isValid) {
throw new IncorrectClaimException(
String.format("The Claim '%s' value doesn't match the required one.", claimName),
claimName,
claim
);
}
}
}
}

View File

@@ -1,55 +0,0 @@
package com.auth0.jwt;
/**
* Contains constants representing the name of the Registered Claim Names as defined in Section 4.1 of
* <a href="https://datatracker.ietf.org/doc/html/rfc7519#section-4.1">RFC 7529</a>
*/
public final class RegisteredClaims {
private RegisteredClaims() {
}
/**
* The "iss" (issuer) claim identifies the principal that issued the JWT.
* Refer RFC 7529 <a href="https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1">Section 4.1.1</a>
*/
public static final String ISSUER = "iss";
/**
* The "sub" (subject) claim identifies the principal that is the subject of the JWT.
* Refer RFC 7529 <a href="https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2">Section 4.1.2</a>
*/
public static final String SUBJECT = "sub";
/**
* The "aud" (audience) claim identifies the recipients that the JWT is intended for.
* Refer RFC 7529 <a href="https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3">Section 4.1.3</a>
*/
public static final String AUDIENCE = "aud";
/**
* The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be
* accepted for processing.
* Refer RFC 7529 <a href="https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4">Section 4.1.4</a>
*/
public static final String EXPIRES_AT = "exp";
/**
* The "nbf" (not before) claim identifies the time before which the JWT MUST NOT be accepted for processing.
* Refer RFC 7529 <a href="https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5">Section 4.1.5</a>
*/
public static final String NOT_BEFORE = "nbf";
/**
* The "iat" (issued at) claim identifies the time at which the JWT was issued.
* Refer RFC 7529 <a href="https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6">Section 4.1.6</a>
*/
public static final String ISSUED_AT = "iat";
/**
* The "jti" (JWT ID) claim provides a unique identifier for the JWT.
* Refer RFC 7529 <a href="https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7">Section 4.1.7</a>
*/
public static final String JWT_ID = "jti";
}

View File

@@ -1,47 +0,0 @@
package com.auth0.jwt;
import com.auth0.jwt.exceptions.JWTDecodeException;
abstract class TokenUtils {
/**
* Splits the given token on the "." chars into a String array with 3 parts.
*
* @param token the string to split.
* @return the array representing the 3 parts of the token.
* @throws JWTDecodeException if the Token doesn't have 3 parts.
*/
static String[] splitToken(String token) throws JWTDecodeException {
if (token == null) {
throw new JWTDecodeException("The token is null.");
}
char delimiter = '.';
int firstPeriodIndex = token.indexOf(delimiter);
if (firstPeriodIndex == -1) {
throw wrongNumberOfParts(0);
}
int secondPeriodIndex = token.indexOf(delimiter, firstPeriodIndex + 1);
if (secondPeriodIndex == -1) {
throw wrongNumberOfParts(2);
}
// too many ?
if (token.indexOf(delimiter, secondPeriodIndex + 1) != -1) {
throw wrongNumberOfParts("> 3");
}
String[] parts = new String[3];
parts[0] = token.substring(0, firstPeriodIndex);
parts[1] = token.substring(firstPeriodIndex + 1, secondPeriodIndex);
parts[2] = token.substring(secondPeriodIndex + 1);
return parts;
}
private static JWTDecodeException wrongNumberOfParts(Object partCount) {
return new JWTDecodeException(String.format("The token was expected to have 3 parts, but got %s.", partCount));
}
}

View File

@@ -1,404 +0,0 @@
package com.auth0.jwt.algorithms;
import com.auth0.jwt.exceptions.SignatureGenerationException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.ECDSAKeyProvider;
import com.auth0.jwt.interfaces.RSAKeyProvider;
import java.security.interfaces.*;
/**
* The Algorithm class represents an algorithm to be used in the Signing or Verification process of a Token.
* <p>
* This class and its subclasses are thread-safe.
*/
@SuppressWarnings("WeakerAccess")
public abstract class Algorithm {
private final String name;
private final String description;
/**
* Creates a new Algorithm instance using SHA256withRSA. Tokens specify this as "RS256".
*
* @param keyProvider the provider of the Public Key and Private Key for the verify and signing instance.
* @return a valid RSA256 Algorithm.
* @throws IllegalArgumentException if the provided Key is null.
*/
public static Algorithm RSA256(RSAKeyProvider keyProvider) throws IllegalArgumentException {
return new RSAAlgorithm("RS256", "SHA256withRSA", keyProvider);
}
/**
* Creates a new Algorithm instance using SHA256withRSA. Tokens specify this as "RS256".
*
* @param publicKey the key to use in the verify instance.
* @param privateKey the key to use in the signing instance.
* @return a valid RSA256 Algorithm.
* @throws IllegalArgumentException if both provided Keys are null.
*/
public static Algorithm RSA256(RSAPublicKey publicKey, RSAPrivateKey privateKey) throws IllegalArgumentException {
return RSA256(RSAAlgorithm.providerForKeys(publicKey, privateKey));
}
/**
* Creates a new Algorithm instance using SHA256withRSA. Tokens specify this as "RS256".
*
* @param key the key to use in the verify or signing instance.
* @return a valid RSA256 Algorithm.
* @throws IllegalArgumentException if the Key Provider is null.
*/
public static Algorithm RSA256(RSAKey key) throws IllegalArgumentException {
RSAPublicKey publicKey = key instanceof RSAPublicKey ? (RSAPublicKey) key : null;
RSAPrivateKey privateKey = key instanceof RSAPrivateKey ? (RSAPrivateKey) key : null;
return RSA256(publicKey, privateKey);
}
/**
* Creates a new Algorithm instance using SHA384withRSA. Tokens specify this as "RS384".
*
* @param keyProvider the provider of the Public Key and Private Key for the verify and signing instance.
* @return a valid RSA384 Algorithm.
* @throws IllegalArgumentException if the Key Provider is null.
*/
public static Algorithm RSA384(RSAKeyProvider keyProvider) throws IllegalArgumentException {
return new RSAAlgorithm("RS384", "SHA384withRSA", keyProvider);
}
/**
* Creates a new Algorithm instance using SHA384withRSA. Tokens specify this as "RS384".
*
* @param publicKey the key to use in the verify instance.
* @param privateKey the key to use in the signing instance.
* @return a valid RSA384 Algorithm.
* @throws IllegalArgumentException if both provided Keys are null.
*/
public static Algorithm RSA384(RSAPublicKey publicKey, RSAPrivateKey privateKey) throws IllegalArgumentException {
return RSA384(RSAAlgorithm.providerForKeys(publicKey, privateKey));
}
/**
* Creates a new Algorithm instance using SHA384withRSA. Tokens specify this as "RS384".
*
* @param key the key to use in the verify or signing instance.
* @return a valid RSA384 Algorithm.
* @throws IllegalArgumentException if the provided Key is null.
*/
public static Algorithm RSA384(RSAKey key) throws IllegalArgumentException {
RSAPublicKey publicKey = key instanceof RSAPublicKey ? (RSAPublicKey) key : null;
RSAPrivateKey privateKey = key instanceof RSAPrivateKey ? (RSAPrivateKey) key : null;
return RSA384(publicKey, privateKey);
}
/**
* Creates a new Algorithm instance using SHA512withRSA. Tokens specify this as "RS512".
*
* @param keyProvider the provider of the Public Key and Private Key for the verify and signing instance.
* @return a valid RSA512 Algorithm.
* @throws IllegalArgumentException if the Key Provider is null.
*/
public static Algorithm RSA512(RSAKeyProvider keyProvider) throws IllegalArgumentException {
return new RSAAlgorithm("RS512", "SHA512withRSA", keyProvider);
}
/**
* Creates a new Algorithm instance using SHA512withRSA. Tokens specify this as "RS512".
*
* @param publicKey the key to use in the verify instance.
* @param privateKey the key to use in the signing instance.
* @return a valid RSA512 Algorithm.
* @throws IllegalArgumentException if both provided Keys are null.
*/
public static Algorithm RSA512(RSAPublicKey publicKey, RSAPrivateKey privateKey) throws IllegalArgumentException {
return RSA512(RSAAlgorithm.providerForKeys(publicKey, privateKey));
}
/**
* Creates a new Algorithm instance using SHA512withRSA. Tokens specify this as "RS512".
*
* @param key the key to use in the verify or signing instance.
* @return a valid RSA512 Algorithm.
* @throws IllegalArgumentException if the provided Key is null.
*/
public static Algorithm RSA512(RSAKey key) throws IllegalArgumentException {
RSAPublicKey publicKey = key instanceof RSAPublicKey ? (RSAPublicKey) key : null;
RSAPrivateKey privateKey = key instanceof RSAPrivateKey ? (RSAPrivateKey) key : null;
return RSA512(publicKey, privateKey);
}
/**
* Creates a new Algorithm instance using HmacSHA256. Tokens specify this as "HS256".
*
* @param secret the secret bytes to use in the verify or signing instance.
* Ensure the length of the secret is at least 256 bit long
* See <a href="https://github.com/auth0/java-jwt#hmac-key-length-and-security">HMAC Key Length and Security in README</a>
* @return a valid HMAC256 Algorithm.
* @throws IllegalArgumentException if the provided Secret is null.
*/
public static Algorithm HMAC256(String secret) throws IllegalArgumentException {
return new HMACAlgorithm("HS256", "HmacSHA256", secret);
}
/**
* Creates a new Algorithm instance using HmacSHA256. Tokens specify this as "HS256".
*
* @param secret the secret bytes to use in the verify or signing instance.
* Ensure the length of the secret is at least 256 bit long
* See <a href="https://github.com/auth0/java-jwt#hmac-key-length-and-security">HMAC Key Length and Security in README</a>
* @return a valid HMAC256 Algorithm.
* @throws IllegalArgumentException if the provided Secret is null.
*/
public static Algorithm HMAC256(byte[] secret) throws IllegalArgumentException {
return new HMACAlgorithm("HS256", "HmacSHA256", secret);
}
/**
* Creates a new Algorithm instance using HmacSHA384. Tokens specify this as "HS384".
*
* @param secret the secret bytes to use in the verify or signing instance.
* Ensure the length of the secret is at least 384 bit long
* See <a href="https://github.com/auth0/java-jwt#hmac-key-length-and-security">HMAC Key Length and Security in README</a>
* @return a valid HMAC384 Algorithm.
* @throws IllegalArgumentException if the provided Secret is null.
*/
public static Algorithm HMAC384(String secret) throws IllegalArgumentException {
return new HMACAlgorithm("HS384", "HmacSHA384", secret);
}
/**
* Creates a new Algorithm instance using HmacSHA384. Tokens specify this as "HS384".
*
* @param secret the secret bytes to use in the verify or signing instance.
* Ensure the length of the secret is at least 384 bit long
* See <a href="https://github.com/auth0/java-jwt#hmac-key-length-and-security">HMAC Key Length and Security in README</a>
* @return a valid HMAC384 Algorithm.
* @throws IllegalArgumentException if the provided Secret is null.
*/
public static Algorithm HMAC384(byte[] secret) throws IllegalArgumentException {
return new HMACAlgorithm("HS384", "HmacSHA384", secret);
}
/**
* Creates a new Algorithm instance using HmacSHA512. Tokens specify this as "HS512".
*
* @param secret the secret bytes to use in the verify or signing instance.
* Ensure the length of the secret is at least 512 bit long
* See <a href="https://github.com/auth0/java-jwt#hmac-key-length-and-security">HMAC Key Length and Security in README</a>
* @return a valid HMAC512 Algorithm.
* @throws IllegalArgumentException if the provided Secret is null.
*/
public static Algorithm HMAC512(String secret) throws IllegalArgumentException {
return new HMACAlgorithm("HS512", "HmacSHA512", secret);
}
/**
* Creates a new Algorithm instance using HmacSHA512. Tokens specify this as "HS512".
*
* @param secret the secret bytes to use in the verify or signing instance.
* Ensure the length of the secret is at least 512 bit long
* See <a href="https://github.com/auth0/java-jwt#hmac-key-length-and-security">HMAC Key Length and Security in README</a>
* @return a valid HMAC512 Algorithm.
* @throws IllegalArgumentException if the provided Secret is null.
*/
public static Algorithm HMAC512(byte[] secret) throws IllegalArgumentException {
return new HMACAlgorithm("HS512", "HmacSHA512", secret);
}
/**
* Creates a new Algorithm instance using SHA256withECDSA. Tokens specify this as "ES256".
*
* @param keyProvider the provider of the Public Key and Private Key for the verify and signing instance.
* @return a valid ECDSA256 Algorithm.
* @throws IllegalArgumentException if the Key Provider is null.
*/
public static Algorithm ECDSA256(ECDSAKeyProvider keyProvider) throws IllegalArgumentException {
return new ECDSAAlgorithm("ES256", "SHA256withECDSA", 32, keyProvider);
}
/**
* Creates a new Algorithm instance using SHA256withECDSA. Tokens specify this as "ES256".
*
* @param publicKey the key to use in the verify instance.
* @param privateKey the key to use in the signing instance.
* @return a valid ECDSA256 Algorithm.
* @throws IllegalArgumentException if the provided Key is null.
*/
public static Algorithm ECDSA256(ECPublicKey publicKey, ECPrivateKey privateKey) throws IllegalArgumentException {
return ECDSA256(ECDSAAlgorithm.providerForKeys(publicKey, privateKey));
}
/**
* Creates a new Algorithm instance using SHA256withECDSA. Tokens specify this as "ES256".
*
* @param key the key to use in the verify or signing instance.
* @return a valid ECDSA256 Algorithm.
* @throws IllegalArgumentException if the provided Key is null.
*/
public static Algorithm ECDSA256(ECKey key) throws IllegalArgumentException {
ECPublicKey publicKey = key instanceof ECPublicKey ? (ECPublicKey) key : null;
ECPrivateKey privateKey = key instanceof ECPrivateKey ? (ECPrivateKey) key : null;
return ECDSA256(publicKey, privateKey);
}
/**
* Creates a new Algorithm instance using SHA384withECDSA. Tokens specify this as "ES384".
*
* @param keyProvider the provider of the Public Key and Private Key for the verify and signing instance.
* @return a valid ECDSA384 Algorithm.
* @throws IllegalArgumentException if the Key Provider is null.
*/
public static Algorithm ECDSA384(ECDSAKeyProvider keyProvider) throws IllegalArgumentException {
return new ECDSAAlgorithm("ES384", "SHA384withECDSA", 48, keyProvider);
}
/**
* Creates a new Algorithm instance using SHA384withECDSA. Tokens specify this as "ES384".
*
* @param publicKey the key to use in the verify instance.
* @param privateKey the key to use in the signing instance.
* @return a valid ECDSA384 Algorithm.
* @throws IllegalArgumentException if the provided Key is null.
*/
public static Algorithm ECDSA384(ECPublicKey publicKey, ECPrivateKey privateKey) throws IllegalArgumentException {
return ECDSA384(ECDSAAlgorithm.providerForKeys(publicKey, privateKey));
}
/**
* Creates a new Algorithm instance using SHA384withECDSA. Tokens specify this as "ES384".
*
* @param key the key to use in the verify or signing instance.
* @return a valid ECDSA384 Algorithm.
* @throws IllegalArgumentException if the provided Key is null.
*/
public static Algorithm ECDSA384(ECKey key) throws IllegalArgumentException {
ECPublicKey publicKey = key instanceof ECPublicKey ? (ECPublicKey) key : null;
ECPrivateKey privateKey = key instanceof ECPrivateKey ? (ECPrivateKey) key : null;
return ECDSA384(publicKey, privateKey);
}
/**
* Creates a new Algorithm instance using SHA512withECDSA. Tokens specify this as "ES512".
*
* @param keyProvider the provider of the Public Key and Private Key for the verify and signing instance.
* @return a valid ECDSA512 Algorithm.
* @throws IllegalArgumentException if the Key Provider is null.
*/
public static Algorithm ECDSA512(ECDSAKeyProvider keyProvider) throws IllegalArgumentException {
return new ECDSAAlgorithm("ES512", "SHA512withECDSA", 66, keyProvider);
}
/**
* Creates a new Algorithm instance using SHA512withECDSA. Tokens specify this as "ES512".
*
* @param publicKey the key to use in the verify instance.
* @param privateKey the key to use in the signing instance.
* @return a valid ECDSA512 Algorithm.
* @throws IllegalArgumentException if the provided Key is null.
*/
public static Algorithm ECDSA512(ECPublicKey publicKey, ECPrivateKey privateKey) throws IllegalArgumentException {
return ECDSA512(ECDSAAlgorithm.providerForKeys(publicKey, privateKey));
}
/**
* Creates a new Algorithm instance using SHA512withECDSA. Tokens specify this as "ES512".
*
* @param key the key to use in the verify or signing instance.
* @return a valid ECDSA512 Algorithm.
* @throws IllegalArgumentException if the provided Key is null.
*/
public static Algorithm ECDSA512(ECKey key) throws IllegalArgumentException {
ECPublicKey publicKey = key instanceof ECPublicKey ? (ECPublicKey) key : null;
ECPrivateKey privateKey = key instanceof ECPrivateKey ? (ECPrivateKey) key : null;
return ECDSA512(publicKey, privateKey);
}
public static Algorithm none() {
return new NoneAlgorithm();
}
protected Algorithm(String name, String description) {
this.name = name;
this.description = description;
}
/**
* Getter for the Id of the Private Key used to sign the tokens.
* This is usually specified as the `kid` claim in the Header.
*
* @return the Key Id that identifies the Signing Key or null if it's not specified.
*/
public String getSigningKeyId() {
return null;
}
/**
* Getter for the name of this Algorithm, as defined in the JWT Standard. i.e. "HS256"
*
* @return the algorithm name.
*/
public String getName() {
return name;
}
/**
* Getter for the description of this Algorithm,
* required when instantiating a Mac or Signature object. i.e. "HmacSHA256"
*
* @return the algorithm description.
*/
String getDescription() {
return description;
}
@Override
public String toString() {
return description;
}
/**
* Verify the given token using this Algorithm instance.
*
* @param jwt the already decoded JWT that it's going to be verified.
* @throws SignatureVerificationException if the Token's Signature is invalid,
* meaning that it doesn't match the signatureBytes,
* or if the Key is invalid.
*/
public abstract void verify(DecodedJWT jwt) throws SignatureVerificationException;
/**
* Sign the given content using this Algorithm instance.
*
* @param headerBytes an array of bytes representing the base64 encoded header content
* to be verified against the signature.
* @param payloadBytes an array of bytes representing the base64 encoded payload content
* to be verified against the signature.
* @return the signature in a base64 encoded array of bytes
* @throws SignatureGenerationException if the Key is invalid.
*/
public byte[] sign(byte[] headerBytes, byte[] payloadBytes) throws SignatureGenerationException {
// default implementation; keep around until sign(byte[]) method is removed
byte[] contentBytes = new byte[headerBytes.length + 1 + payloadBytes.length];
System.arraycopy(headerBytes, 0, contentBytes, 0, headerBytes.length);
contentBytes[headerBytes.length] = (byte) '.';
System.arraycopy(payloadBytes, 0, contentBytes, headerBytes.length + 1, payloadBytes.length);
return sign(contentBytes);
}
/**
* Sign the given content using this Algorithm instance.
* To get the correct JWT Signature, ensure the content is in the format {HEADER}.{PAYLOAD}
*
* @param contentBytes an array of bytes representing the base64 encoded content
* to be verified against the signature.
* @return the signature in a base64 encoded array of bytes
* @throws SignatureGenerationException if the Key is invalid.
*/
public abstract byte[] sign(byte[] contentBytes) throws SignatureGenerationException;
}

View File

@@ -1,208 +0,0 @@
package com.auth0.jwt.algorithms;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
/**
* Class used to perform the signature hash calculations.
* <p>
* This class is thread-safe.
*/
class CryptoHelper {
private static final byte JWT_PART_SEPARATOR = (byte) 46;
/**
* Verify signature for JWT header and payload.
*
* @param algorithm algorithm name.
* @param secretBytes algorithm secret.
* @param header JWT header.
* @param payload JWT payload.
* @param signatureBytes JWT signature.
* @return true if signature is valid.
* @throws NoSuchAlgorithmException if the algorithm is not supported.
* @throws InvalidKeyException if the given key is inappropriate for initializing the specified algorithm.
*/
boolean verifySignatureFor(
String algorithm,
byte[] secretBytes,
String header,
String payload,
byte[] signatureBytes
) throws NoSuchAlgorithmException, InvalidKeyException {
return verifySignatureFor(algorithm, secretBytes,
header.getBytes(StandardCharsets.UTF_8), payload.getBytes(StandardCharsets.UTF_8), signatureBytes);
}
/**
* Verify signature for JWT header and payload.
*
* @param algorithm algorithm name.
* @param secretBytes algorithm secret.
* @param headerBytes JWT header.
* @param payloadBytes JWT payload.
* @param signatureBytes JWT signature.
* @return true if signature is valid.
* @throws NoSuchAlgorithmException if the algorithm is not supported.
* @throws InvalidKeyException if the given key is inappropriate for initializing the specified algorithm.
*/
boolean verifySignatureFor(
String algorithm,
byte[] secretBytes,
byte[] headerBytes,
byte[] payloadBytes,
byte[] signatureBytes
) throws NoSuchAlgorithmException, InvalidKeyException {
return MessageDigest.isEqual(createSignatureFor(algorithm, secretBytes, headerBytes, payloadBytes),
signatureBytes);
}
/**
* Verify signature for JWT header and payload.
*
* @param algorithm algorithm name.
* @param publicKey algorithm public key.
* @param header JWT header.
* @param payload JWT payload.
* @param signatureBytes JWT signature.
* @return true if signature is valid.
* @throws NoSuchAlgorithmException if the algorithm is not supported.
* @throws InvalidKeyException if the given key is inappropriate for initializing the specified algorithm.
*/
boolean verifySignatureFor(
String algorithm,
PublicKey publicKey,
String header,
String payload,
byte[] signatureBytes
) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
return verifySignatureFor(algorithm, publicKey, header.getBytes(StandardCharsets.UTF_8),
payload.getBytes(StandardCharsets.UTF_8), signatureBytes);
}
/**
* Verify signature for JWT header and payload using a public key.
*
* @param algorithm algorithm name.
* @param publicKey the public key to use for verification.
* @param headerBytes JWT header.
* @param payloadBytes JWT payload.
* @param signatureBytes JWT signature.
* @return true if signature is valid.
* @throws NoSuchAlgorithmException if the algorithm is not supported.
* @throws InvalidKeyException if the given key is inappropriate for initializing the specified algorithm.
*/
boolean verifySignatureFor(
String algorithm,
PublicKey publicKey,
byte[] headerBytes,
byte[] payloadBytes,
byte[] signatureBytes
) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
final Signature s = Signature.getInstance(algorithm);
s.initVerify(publicKey);
s.update(headerBytes);
s.update(JWT_PART_SEPARATOR);
s.update(payloadBytes);
return s.verify(signatureBytes);
}
/**
* Create signature for JWT header and payload using a private key.
*
* @param algorithm algorithm name.
* @param privateKey the private key to use for signing.
* @param headerBytes JWT header.
* @param payloadBytes JWT payload.
* @return the signature bytes.
* @throws NoSuchAlgorithmException if the algorithm is not supported.
* @throws InvalidKeyException if the given key is inappropriate for initializing the specified algorithm.
* @throws SignatureException if this signature object is not initialized properly
* or if this signature algorithm is unable to process the input data provided.
*/
byte[] createSignatureFor(
String algorithm,
PrivateKey privateKey,
byte[] headerBytes,
byte[] payloadBytes
) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
final Signature s = Signature.getInstance(algorithm);
s.initSign(privateKey);
s.update(headerBytes);
s.update(JWT_PART_SEPARATOR);
s.update(payloadBytes);
return s.sign();
}
/**
* Create signature for JWT header and payload.
*
* @param algorithm algorithm name.
* @param secretBytes algorithm secret.
* @param headerBytes JWT header.
* @param payloadBytes JWT payload.
* @return the signature bytes.
* @throws NoSuchAlgorithmException if the algorithm is not supported.
* @throws InvalidKeyException if the given key is inappropriate for initializing the specified algorithm.
*/
byte[] createSignatureFor(
String algorithm,
byte[] secretBytes,
byte[] headerBytes,
byte[] payloadBytes
) throws NoSuchAlgorithmException, InvalidKeyException {
final Mac mac = Mac.getInstance(algorithm);
mac.init(new SecretKeySpec(secretBytes, algorithm));
mac.update(headerBytes);
mac.update(JWT_PART_SEPARATOR);
return mac.doFinal(payloadBytes);
}
/**
* Create signature.
* To get the correct JWT Signature, ensure the content is in the format {HEADER}.{PAYLOAD}
*
* @param algorithm algorithm name.
* @param secretBytes algorithm secret.
* @param contentBytes the content to be signed.
* @return the signature bytes.
* @throws NoSuchAlgorithmException if the algorithm is not supported.
* @throws InvalidKeyException if the given key is inappropriate for initializing the specified algorithm.
*/
byte[] createSignatureFor(String algorithm, byte[] secretBytes, byte[] contentBytes)
throws NoSuchAlgorithmException, InvalidKeyException {
final Mac mac = Mac.getInstance(algorithm);
mac.init(new SecretKeySpec(secretBytes, algorithm));
return mac.doFinal(contentBytes);
}
/**
* Create signature using a private key.
* To get the correct JWT Signature, ensure the content is in the format {HEADER}.{PAYLOAD}
*
* @param algorithm algorithm name.
* @param privateKey the private key to use for signing.
* @param contentBytes the content to be signed.
* @return the signature bytes.
* @throws NoSuchAlgorithmException if the algorithm is not supported.
* @throws InvalidKeyException if the given key is inappropriate for initializing the specified algorithm.
* @throws SignatureException if this signature object is not initialized properly
* or if this signature algorithm is unable to process the input data provided.
*/
byte[] createSignatureFor(
String algorithm,
PrivateKey privateKey,
byte[] contentBytes
) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
final Signature s = Signature.getInstance(algorithm);
s.initSign(privateKey);
s.update(contentBytes);
return s.sign();
}
}

View File

@@ -1,306 +0,0 @@
package com.auth0.jwt.algorithms;
import com.auth0.jwt.exceptions.SignatureGenerationException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.ECDSAKeyProvider;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.util.Base64;
/**
* Subclass representing an Elliptic Curve signing algorithm
* <p>
* This class is thread-safe.
*/
class ECDSAAlgorithm extends Algorithm {
private final ECDSAKeyProvider keyProvider;
private final CryptoHelper crypto;
private final int ecNumberSize;
//Visible for testing
ECDSAAlgorithm(CryptoHelper crypto, String id, String algorithm, int ecNumberSize, ECDSAKeyProvider keyProvider)
throws IllegalArgumentException {
super(id, algorithm);
if (keyProvider == null) {
throw new IllegalArgumentException("The Key Provider cannot be null.");
}
this.keyProvider = keyProvider;
this.crypto = crypto;
this.ecNumberSize = ecNumberSize;
}
ECDSAAlgorithm(String id, String algorithm, int ecNumberSize, ECDSAKeyProvider keyProvider)
throws IllegalArgumentException {
this(new CryptoHelper(), id, algorithm, ecNumberSize, keyProvider);
}
@Override
public void verify(DecodedJWT jwt) throws SignatureVerificationException {
try {
byte[] signatureBytes = Base64.getUrlDecoder().decode(jwt.getSignature());
ECPublicKey publicKey = keyProvider.getPublicKeyById(jwt.getKeyId());
if (publicKey == null) {
throw new IllegalStateException("The given Public Key is null.");
}
validateSignatureStructure(signatureBytes, publicKey);
boolean valid = crypto.verifySignatureFor(
getDescription(), publicKey, jwt.getHeader(), jwt.getPayload(), JOSEToDER(signatureBytes));
if (!valid) {
throw new SignatureVerificationException(this);
}
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException
| IllegalStateException | IllegalArgumentException e) {
throw new SignatureVerificationException(this, e);
}
}
@Override
public byte[] sign(byte[] headerBytes, byte[] payloadBytes) throws SignatureGenerationException {
try {
ECPrivateKey privateKey = keyProvider.getPrivateKey();
if (privateKey == null) {
throw new IllegalStateException("The given Private Key is null.");
}
byte[] signature = crypto.createSignatureFor(getDescription(), privateKey, headerBytes, payloadBytes);
return DERToJOSE(signature);
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException | IllegalStateException e) {
throw new SignatureGenerationException(this, e);
}
}
@Override
public byte[] sign(byte[] contentBytes) throws SignatureGenerationException {
try {
ECPrivateKey privateKey = keyProvider.getPrivateKey();
if (privateKey == null) {
throw new IllegalStateException("The given Private Key is null.");
}
byte[] signature = crypto.createSignatureFor(getDescription(), privateKey, contentBytes);
return DERToJOSE(signature);
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException | IllegalStateException e) {
throw new SignatureGenerationException(this, e);
}
}
@Override
public String getSigningKeyId() {
return keyProvider.getPrivateKeyId();
}
//Visible for testing
byte[] DERToJOSE(byte[] derSignature) throws SignatureException {
// DER Structure: http://crypto.stackexchange.com/a/1797
boolean derEncoded = derSignature[0] == 0x30 && derSignature.length != ecNumberSize * 2;
if (!derEncoded) {
throw new SignatureException("Invalid DER signature format.");
}
final byte[] joseSignature = new byte[ecNumberSize * 2];
//Skip 0x30
int offset = 1;
if (derSignature[1] == (byte) 0x81) {
//Skip sign
offset++;
}
//Convert to unsigned. Should match DER length - offset
int encodedLength = derSignature[offset++] & 0xff;
if (encodedLength != derSignature.length - offset) {
throw new SignatureException("Invalid DER signature format.");
}
//Skip 0x02
offset++;
//Obtain R number length (Includes padding) and skip it
int rlength = derSignature[offset++];
if (rlength > ecNumberSize + 1) {
throw new SignatureException("Invalid DER signature format.");
}
int rpadding = ecNumberSize - rlength;
//Retrieve R number
System.arraycopy(derSignature, offset + Math.max(-rpadding, 0),
joseSignature, Math.max(rpadding, 0), rlength + Math.min(rpadding, 0));
//Skip R number and 0x02
offset += rlength + 1;
//Obtain S number length. (Includes padding)
int slength = derSignature[offset++];
if (slength > ecNumberSize + 1) {
throw new SignatureException("Invalid DER signature format.");
}
int spadding = ecNumberSize - slength;
//Retrieve R number
System.arraycopy(derSignature, offset + Math.max(-spadding, 0), joseSignature,
ecNumberSize + Math.max(spadding, 0), slength + Math.min(spadding, 0));
return joseSignature;
}
/**
* Added check for extra protection against CVE-2022-21449.
* This method ensures the signature's structure is as expected.
*
* @param joseSignature is the signature from the JWT
* @param publicKey public key used to verify the JWT
* @throws SignatureException if the signature's structure is not as per expectation
*/
// Visible for testing
void validateSignatureStructure(byte[] joseSignature, ECPublicKey publicKey) throws SignatureException {
// check signature length, moved this check from JOSEToDER method
if (joseSignature.length != ecNumberSize * 2) {
throw new SignatureException("Invalid JOSE signature format.");
}
if (isAllZeros(joseSignature)) {
throw new SignatureException("Invalid signature format.");
}
// get R
byte[] rBytes = new byte[ecNumberSize];
System.arraycopy(joseSignature, 0, rBytes, 0, ecNumberSize);
if (isAllZeros(rBytes)) {
throw new SignatureException("Invalid signature format.");
}
// get S
byte[] sBytes = new byte[ecNumberSize];
System.arraycopy(joseSignature, ecNumberSize, sBytes, 0, ecNumberSize);
if (isAllZeros(sBytes)) {
throw new SignatureException("Invalid signature format.");
}
//moved this check from JOSEToDER method
int rPadding = countPadding(joseSignature, 0, ecNumberSize);
int sPadding = countPadding(joseSignature, ecNumberSize, joseSignature.length);
int rLength = ecNumberSize - rPadding;
int sLength = ecNumberSize - sPadding;
int length = 2 + rLength + 2 + sLength;
if (length > 255) {
throw new SignatureException("Invalid JOSE signature format.");
}
BigInteger order = publicKey.getParams().getOrder();
BigInteger r = new BigInteger(1, rBytes);
BigInteger s = new BigInteger(1, sBytes);
// R and S must be less than N
if (order.compareTo(r) < 1) {
throw new SignatureException("Invalid signature format.");
}
if (order.compareTo(s) < 1) {
throw new SignatureException("Invalid signature format.");
}
}
//Visible for testing
byte[] JOSEToDER(byte[] joseSignature) throws SignatureException {
// Retrieve R and S number's length and padding.
int rPadding = countPadding(joseSignature, 0, ecNumberSize);
int sPadding = countPadding(joseSignature, ecNumberSize, joseSignature.length);
int rLength = ecNumberSize - rPadding;
int sLength = ecNumberSize - sPadding;
int length = 2 + rLength + 2 + sLength;
final byte[] derSignature;
int offset;
if (length > 0x7f) {
derSignature = new byte[3 + length];
derSignature[1] = (byte) 0x81;
offset = 2;
} else {
derSignature = new byte[2 + length];
offset = 1;
}
// DER Structure: http://crypto.stackexchange.com/a/1797
// Header with signature length info
derSignature[0] = (byte) 0x30;
derSignature[offset++] = (byte) (length & 0xff);
// Header with "min R" number length
derSignature[offset++] = (byte) 0x02;
derSignature[offset++] = (byte) rLength;
// R number
if (rPadding < 0) {
//Sign
derSignature[offset++] = (byte) 0x00;
System.arraycopy(joseSignature, 0, derSignature, offset, ecNumberSize);
offset += ecNumberSize;
} else {
int copyLength = Math.min(ecNumberSize, rLength);
System.arraycopy(joseSignature, rPadding, derSignature, offset, copyLength);
offset += copyLength;
}
// Header with "min S" number length
derSignature[offset++] = (byte) 0x02;
derSignature[offset++] = (byte) sLength;
// S number
if (sPadding < 0) {
//Sign
derSignature[offset++] = (byte) 0x00;
System.arraycopy(joseSignature, ecNumberSize, derSignature, offset, ecNumberSize);
} else {
System.arraycopy(joseSignature, ecNumberSize + sPadding, derSignature, offset,
Math.min(ecNumberSize, sLength));
}
return derSignature;
}
private boolean isAllZeros(byte[] bytes) {
for (byte b : bytes) {
if (b != 0) {
return false;
}
}
return true;
}
private int countPadding(byte[] bytes, int fromIndex, int toIndex) {
int padding = 0;
while (fromIndex + padding < toIndex && bytes[fromIndex + padding] == 0) {
padding++;
}
return (bytes[fromIndex + padding] & 0xff) > 0x7f ? padding - 1 : padding;
}
//Visible for testing
static ECDSAKeyProvider providerForKeys(final ECPublicKey publicKey, final ECPrivateKey privateKey) {
if (publicKey == null && privateKey == null) {
throw new IllegalArgumentException("Both provided Keys cannot be null.");
}
return new ECDSAKeyProvider() {
@Override
public ECPublicKey getPublicKeyById(String keyId) {
return publicKey;
}
@Override
public ECPrivateKey getPrivateKey() {
return privateKey;
}
@Override
public String getPrivateKeyId() {
return null;
}
};
}
}

View File

@@ -1,81 +0,0 @@
package com.auth0.jwt.algorithms;
import com.auth0.jwt.exceptions.SignatureGenerationException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
/**
* Subclass representing an Hash-based MAC signing algorithm
* <p>
* This class is thread-safe.
*/
class HMACAlgorithm extends Algorithm {
private final CryptoHelper crypto;
private final byte[] secret;
//Visible for testing
HMACAlgorithm(CryptoHelper crypto, String id, String algorithm, byte[] secretBytes)
throws IllegalArgumentException {
super(id, algorithm);
if (secretBytes == null) {
throw new IllegalArgumentException("The Secret cannot be null");
}
this.secret = Arrays.copyOf(secretBytes, secretBytes.length);
this.crypto = crypto;
}
HMACAlgorithm(String id, String algorithm, byte[] secretBytes) throws IllegalArgumentException {
this(new CryptoHelper(), id, algorithm, secretBytes);
}
HMACAlgorithm(String id, String algorithm, String secret) throws IllegalArgumentException {
this(new CryptoHelper(), id, algorithm, getSecretBytes(secret));
}
//Visible for testing
static byte[] getSecretBytes(String secret) throws IllegalArgumentException {
if (secret == null) {
throw new IllegalArgumentException("The Secret cannot be null");
}
return secret.getBytes(StandardCharsets.UTF_8);
}
@Override
public void verify(DecodedJWT jwt) throws SignatureVerificationException {
try {
byte[] signatureBytes = Base64.getUrlDecoder().decode(jwt.getSignature());
boolean valid = crypto.verifySignatureFor(
getDescription(), secret, jwt.getHeader(), jwt.getPayload(), signatureBytes);
if (!valid) {
throw new SignatureVerificationException(this);
}
} catch (IllegalStateException | InvalidKeyException | NoSuchAlgorithmException | IllegalArgumentException e) {
throw new SignatureVerificationException(this, e);
}
}
@Override
public byte[] sign(byte[] headerBytes, byte[] payloadBytes) throws SignatureGenerationException {
try {
return crypto.createSignatureFor(getDescription(), secret, headerBytes, payloadBytes);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new SignatureGenerationException(this, e);
}
}
@Override
public byte[] sign(byte[] contentBytes) throws SignatureGenerationException {
try {
return crypto.createSignatureFor(getDescription(), secret, contentBytes);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new SignatureGenerationException(this, e);
}
}
}

View File

@@ -1,36 +0,0 @@
package com.auth0.jwt.algorithms;
import com.auth0.jwt.exceptions.SignatureGenerationException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Base64;
class NoneAlgorithm extends Algorithm {
NoneAlgorithm() {
super("none", "none");
}
@Override
public void verify(DecodedJWT jwt) throws SignatureVerificationException {
try {
byte[] signatureBytes = Base64.getUrlDecoder().decode(jwt.getSignature());
if (signatureBytes.length > 0) {
throw new SignatureVerificationException(this);
}
} catch (IllegalArgumentException e) {
throw new SignatureVerificationException(this, e);
}
}
@Override
public byte[] sign(byte[] headerBytes, byte[] payloadBytes) throws SignatureGenerationException {
return new byte[0];
}
@Override
public byte[] sign(byte[] contentBytes) throws SignatureGenerationException {
return new byte[0];
}
}

View File

@@ -1,112 +0,0 @@
package com.auth0.jwt.algorithms;
import com.auth0.jwt.exceptions.SignatureGenerationException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.RSAKeyProvider;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;
/**
* Subclass representing an RSA signing algorithm
* <p>
* This class is thread-safe.
*/
class RSAAlgorithm extends Algorithm {
private final RSAKeyProvider keyProvider;
private final CryptoHelper crypto;
//Visible for testing
RSAAlgorithm(CryptoHelper crypto, String id, String algorithm, RSAKeyProvider keyProvider)
throws IllegalArgumentException {
super(id, algorithm);
if (keyProvider == null) {
throw new IllegalArgumentException("The Key Provider cannot be null.");
}
this.keyProvider = keyProvider;
this.crypto = crypto;
}
RSAAlgorithm(String id, String algorithm, RSAKeyProvider keyProvider) throws IllegalArgumentException {
this(new CryptoHelper(), id, algorithm, keyProvider);
}
@Override
public void verify(DecodedJWT jwt) throws SignatureVerificationException {
try {
byte[] signatureBytes = Base64.getUrlDecoder().decode(jwt.getSignature());
RSAPublicKey publicKey = keyProvider.getPublicKeyById(jwt.getKeyId());
if (publicKey == null) {
throw new IllegalStateException("The given Public Key is null.");
}
boolean valid = crypto.verifySignatureFor(
getDescription(), publicKey, jwt.getHeader(), jwt.getPayload(), signatureBytes);
if (!valid) {
throw new SignatureVerificationException(this);
}
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException
| IllegalArgumentException | IllegalStateException e) {
throw new SignatureVerificationException(this, e);
}
}
@Override
public byte[] sign(byte[] headerBytes, byte[] payloadBytes) throws SignatureGenerationException {
try {
RSAPrivateKey privateKey = keyProvider.getPrivateKey();
if (privateKey == null) {
throw new IllegalStateException("The given Private Key is null.");
}
return crypto.createSignatureFor(getDescription(), privateKey, headerBytes, payloadBytes);
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException | IllegalStateException e) {
throw new SignatureGenerationException(this, e);
}
}
@Override
public byte[] sign(byte[] contentBytes) throws SignatureGenerationException {
try {
RSAPrivateKey privateKey = keyProvider.getPrivateKey();
if (privateKey == null) {
throw new IllegalStateException("The given Private Key is null.");
}
return crypto.createSignatureFor(getDescription(), privateKey, contentBytes);
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException | IllegalStateException e) {
throw new SignatureGenerationException(this, e);
}
}
@Override
public String getSigningKeyId() {
return keyProvider.getPrivateKeyId();
}
//Visible for testing
static RSAKeyProvider providerForKeys(final RSAPublicKey publicKey, final RSAPrivateKey privateKey) {
if (publicKey == null && privateKey == null) {
throw new IllegalArgumentException("Both provided Keys cannot be null.");
}
return new RSAKeyProvider() {
@Override
public RSAPublicKey getPublicKeyById(String keyId) {
return publicKey;
}
@Override
public RSAPrivateKey getPrivateKey() {
return privateKey;
}
@Override
public String getPrivateKeyId() {
return null;
}
};
}
}

View File

@@ -1,10 +0,0 @@
package com.auth0.jwt.exceptions;
/**
* The exception that will be thrown if the exception doesn't match the one mentioned in the JWT Header.
*/
public class AlgorithmMismatchException extends JWTVerificationException {
public AlgorithmMismatchException(String message) {
super(message);
}
}

View File

@@ -1,44 +0,0 @@
package com.auth0.jwt.exceptions;
import com.auth0.jwt.interfaces.Claim;
/**
* This exception is thrown when the expected value is not found while verifying the Claims.
*/
public class IncorrectClaimException extends InvalidClaimException {
private final String claimName;
private final Claim claimValue;
/**
* Used internally to construct the IncorrectClaimException which is thrown when there is verification
* failure for a Claim that exists.
*
* @param message The error message
* @param claimName The Claim name for which verification failed
* @param claim The Claim value for which verification failed
*/
public IncorrectClaimException(String message, String claimName, Claim claim) {
super(message);
this.claimName = claimName;
this.claimValue = claim;
}
/**
* This method can be used to fetch the name for which the Claim verification failed.
*
* @return The claim name for which the verification failed.
*/
public String getClaimName() {
return claimName;
}
/**
* This method can be used to fetch the value for which the Claim verification failed.
*
* @return The value for which the verification failed
*/
public Claim getClaimValue() {
return claimValue;
}
}

View File

@@ -1,10 +0,0 @@
package com.auth0.jwt.exceptions;
/**
* The exception that will be thrown while verifying Claims of a JWT.
*/
public class InvalidClaimException extends JWTVerificationException {
public InvalidClaimException(String message) {
super(message);
}
}

View File

@@ -1,10 +0,0 @@
package com.auth0.jwt.exceptions;
/**
* The exception that is thrown when a JWT cannot be created.
*/
public class JWTCreationException extends RuntimeException {
public JWTCreationException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,14 +0,0 @@
package com.auth0.jwt.exceptions;
/**
* The exception that is thrown when any part of the token contained an invalid JWT or JSON format.
*/
public class JWTDecodeException extends JWTVerificationException {
public JWTDecodeException(String message) {
this(message, null);
}
public JWTDecodeException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,14 +0,0 @@
package com.auth0.jwt.exceptions;
/**
* Parent to all the exception thrown while verifying a JWT.
*/
public class JWTVerificationException extends RuntimeException {
public JWTVerificationException(String message) {
this(message, null);
}
public JWTVerificationException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,23 +0,0 @@
package com.auth0.jwt.exceptions;
/**
* This exception is thrown when the claim to be verified is missing.
*/
public class MissingClaimException extends InvalidClaimException {
private final String claimName;
public MissingClaimException(String claimName) {
super(String.format("The Claim '%s' is not present in the JWT.", claimName));
this.claimName = claimName;
}
/**
* This method can be used to fetch the name for which the Claim is missing during the verification.
*
* @return The name of the Claim that doesn't exist.
*/
public String getClaimName() {
return claimName;
}
}

View File

@@ -1,12 +0,0 @@
package com.auth0.jwt.exceptions;
import com.auth0.jwt.algorithms.Algorithm;
/**
* The exception that is thrown when signature is not able to be generated.
*/
public class SignatureGenerationException extends JWTCreationException {
public SignatureGenerationException(Algorithm algorithm, Throwable cause) {
super("The Token's Signature couldn't be generated when signing using the Algorithm: " + algorithm, cause);
}
}

View File

@@ -1,16 +0,0 @@
package com.auth0.jwt.exceptions;
import com.auth0.jwt.algorithms.Algorithm;
/**
* The exception that is thrown if the Signature verification fails.
*/
public class SignatureVerificationException extends JWTVerificationException {
public SignatureVerificationException(Algorithm algorithm) {
this(algorithm, null);
}
public SignatureVerificationException(Algorithm algorithm, Throwable cause) {
super("The Token's Signature resulted invalid when verified using the Algorithm: " + algorithm, cause);
}
}

View File

@@ -1,22 +0,0 @@
package com.auth0.jwt.exceptions;
import java.time.Instant;
/**
* The exception that is thrown if the token is expired.
*/
public class TokenExpiredException extends JWTVerificationException {
private static final long serialVersionUID = -7076928975713577708L;
private final Instant expiredOn;
public TokenExpiredException(String message, Instant expiredOn) {
super(message);
this.expiredOn = expiredOn;
}
public Instant getExpiredOn() {
return expiredOn;
}
}

View File

@@ -1,71 +0,0 @@
package com.auth0.jwt.impl;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.Header;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import static com.auth0.jwt.impl.JsonNodeClaim.extractClaim;
/**
* The BasicHeader class implements the Header interface.
*/
class BasicHeader implements Header, Serializable {
private static final long serialVersionUID = -4659137688548605095L;
private final String algorithm;
private final String type;
private final String contentType;
private final String keyId;
private final Map<String, JsonNode> tree;
private final ObjectCodec objectCodec;
BasicHeader(
String algorithm,
String type,
String contentType,
String keyId,
Map<String, JsonNode> tree,
ObjectCodec objectCodec
) {
this.algorithm = algorithm;
this.type = type;
this.contentType = contentType;
this.keyId = keyId;
this.tree = tree == null ? Collections.emptyMap() : Collections.unmodifiableMap(tree);
this.objectCodec = objectCodec;
}
Map<String, JsonNode> getTree() {
return tree;
}
@Override
public String getAlgorithm() {
return algorithm;
}
@Override
public String getType() {
return type;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public String getKeyId() {
return keyId;
}
@Override
public Claim getHeaderClaim(String name) {
return extractClaim(name, tree, objectCodec);
}
}

View File

@@ -1,19 +0,0 @@
package com.auth0.jwt.impl;
import java.util.HashMap;
import java.util.Map;
/**
* The ClaimsHolder class is just a wrapper for the Map of Claims used for building a JWT.
*/
public abstract class ClaimsHolder {
private Map<String, Object> claims;
protected ClaimsHolder(Map<String, Object> claims) {
this.claims = claims == null ? new HashMap<>() : claims;
}
Map<String, Object> getClaims() {
return claims;
}
}

View File

@@ -1,86 +0,0 @@
package com.auth0.jwt.impl;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* Custom serializer used to write the resulting JWT.
*
* @param <T> the type this serializer operates on.
*/
public class ClaimsSerializer<T extends ClaimsHolder> extends StdSerializer<T> {
public ClaimsSerializer(Class<T> t) {
super(t);
}
@Override
public void serialize(T holder, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
for (Map.Entry<String, Object> entry : holder.getClaims().entrySet()) {
writeClaim(entry, gen);
}
gen.writeEndObject();
}
/**
* Writes the given entry to the JSON representation. Custom claim serialization handling can override this method
* to provide use-case specific serialization. Implementors who override this method must write
* the field name and the field value.
*
* @param entry The entry that corresponds to the JSON field to write
* @param gen The {@code JsonGenerator} to use
* @throws IOException if there is either an underlying I/O problem or encoding issue at format layer
*/
protected void writeClaim(Map.Entry<String, Object> entry, JsonGenerator gen) throws IOException {
gen.writeFieldName(entry.getKey());
handleSerialization(entry.getValue(), gen);
}
private static void handleSerialization(Object value, JsonGenerator gen) throws IOException {
if (value instanceof Date) {
gen.writeNumber(dateToSeconds((Date) value));
} else if (value instanceof Instant) { // EXPIRES_AT, ISSUED_AT, NOT_BEFORE, custom Instant claims
gen.writeNumber(instantToSeconds((Instant) value));
} else if (value instanceof Map) {
serializeMap((Map<?, ?>) value, gen);
} else if (value instanceof List) {
serializeList((List<?>) value, gen);
} else {
gen.writeObject(value);
}
}
private static void serializeMap(Map<?, ?> map, JsonGenerator gen) throws IOException {
gen.writeStartObject();
for (Map.Entry<?, ?> entry : map.entrySet()) {
gen.writeFieldName((String) entry.getKey());
Object value = entry.getValue();
handleSerialization(value, gen);
}
gen.writeEndObject();
}
private static void serializeList(List<?> list, JsonGenerator gen) throws IOException {
gen.writeStartArray();
for (Object entry : list) {
handleSerialization(entry, gen);
}
gen.writeEndArray();
}
private static long instantToSeconds(Instant instant) {
return instant.getEpochSecond();
}
private static long dateToSeconds(Date date) {
return date.getTime() / 1000;
}
}

View File

@@ -1,25 +0,0 @@
package com.auth0.jwt.impl;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
/**
* This holds the checks that are run to verify a JWT.
*/
public interface ExpectedCheckHolder {
/**
* The claim name that will be checked.
*
* @return the claim name
*/
String getClaimName();
/**
* The verification that will be run.
*
* @param claim the claim for which verification is done
* @param decodedJWT the JWT on which verification is done
* @return whether the verification passed or not
*/
boolean verify(Claim claim, DecodedJWT decodedJWT);
}

View File

@@ -1,12 +0,0 @@
package com.auth0.jwt.impl;
import java.util.Map;
/**
* Holds the header claims when serializing a JWT.
*/
public final class HeaderClaimsHolder extends ClaimsHolder {
public HeaderClaimsHolder(Map<String, Object> claims) {
super(claims);
}
}

View File

@@ -1,50 +0,0 @@
package com.auth0.jwt.impl;
import com.auth0.jwt.HeaderParams;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Header;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.util.Map;
/**
* Jackson deserializer implementation for converting from JWT Header parts.
* <p>
* This class is thread-safe.
*
* @see JWTParser
*/
class HeaderDeserializer extends StdDeserializer<Header> {
HeaderDeserializer() {
super(Header.class);
}
@Override
public Header deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
Map<String, JsonNode> tree = p.getCodec().readValue(p, new TypeReference<Map<String, JsonNode>>() {
});
if (tree == null) {
throw new JWTDecodeException("Parsing the Header's JSON resulted on a Null map");
}
String algorithm = getString(tree, HeaderParams.ALGORITHM);
String type = getString(tree, HeaderParams.TYPE);
String contentType = getString(tree, HeaderParams.CONTENT_TYPE);
String keyId = getString(tree, HeaderParams.KEY_ID);
return new BasicHeader(algorithm, type, contentType, keyId, tree, p.getCodec());
}
String getString(Map<String, JsonNode> tree, String claimName) {
JsonNode node = tree.get(claimName);
if (node == null || node.isNull()) {
return null;
}
return node.asText(null);
}
}

View File

@@ -1,10 +0,0 @@
package com.auth0.jwt.impl;
/**
* Responsible for serializing a JWT's header representation to JSON.
*/
public class HeaderSerializer extends ClaimsSerializer<HeaderClaimsHolder> {
public HeaderSerializer() {
super(HeaderClaimsHolder.class);
}
}

View File

@@ -1,92 +0,0 @@
package com.auth0.jwt.impl;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Header;
import com.auth0.jwt.interfaces.JWTPartsParser;
import com.auth0.jwt.interfaces.Payload;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
/**
* This class helps in decoding the Header and Payload of the JWT using
* {@link HeaderSerializer} and {@link PayloadSerializer}.
*/
public class JWTParser implements JWTPartsParser {
private static final ObjectMapper DEFAULT_OBJECT_MAPPER = createDefaultObjectMapper();
private static final ObjectReader DEFAULT_PAYLOAD_READER = DEFAULT_OBJECT_MAPPER.readerFor(Payload.class);
private static final ObjectReader DEFAULT_HEADER_READER = DEFAULT_OBJECT_MAPPER.readerFor(Header.class);
private final ObjectReader payloadReader;
private final ObjectReader headerReader;
public JWTParser() {
this.payloadReader = DEFAULT_PAYLOAD_READER;
this.headerReader = DEFAULT_HEADER_READER;
}
JWTParser(ObjectMapper mapper) {
addDeserializers(mapper);
this.payloadReader = mapper.readerFor(Payload.class);
this.headerReader = mapper.readerFor(Header.class);
}
@Override
public Payload parsePayload(String json) throws JWTDecodeException {
if (json == null) {
throw decodeException();
}
try {
return payloadReader.readValue(json);
} catch (IOException e) {
throw decodeException(json);
}
}
@Override
public Header parseHeader(String json) throws JWTDecodeException {
if (json == null) {
throw decodeException();
}
try {
return headerReader.readValue(json);
} catch (IOException e) {
throw decodeException(json);
}
}
static void addDeserializers(ObjectMapper mapper) {
SimpleModule module = new SimpleModule();
module.addDeserializer(Payload.class, new PayloadDeserializer());
module.addDeserializer(Header.class, new HeaderDeserializer());
mapper.registerModule(module);
}
static ObjectMapper getDefaultObjectMapper() {
return DEFAULT_OBJECT_MAPPER;
}
private static ObjectMapper createDefaultObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
addDeserializers(mapper);
return mapper;
}
private static JWTDecodeException decodeException() {
return decodeException(null);
}
private static JWTDecodeException decodeException(String json) {
return new JWTDecodeException(String.format("The string '%s' doesn't have a valid JSON format.", json));
}
}

View File

@@ -1,182 +0,0 @@
package com.auth0.jwt.impl;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Claim;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.lang.reflect.Array;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* The JsonNodeClaim retrieves a claim value from a JsonNode object.
*/
class JsonNodeClaim implements Claim {
private final ObjectCodec codec;
private final JsonNode data;
private JsonNodeClaim(JsonNode node, ObjectCodec codec) {
this.data = node;
this.codec = codec;
}
@Override
public Boolean asBoolean() {
return isMissing() || isNull() || !data.isBoolean() ? null : data.asBoolean();
}
@Override
public Integer asInt() {
return isMissing() || isNull() || !data.isNumber() ? null : data.asInt();
}
@Override
public Long asLong() {
return isMissing() || isNull() || !data.isNumber() ? null : data.asLong();
}
@Override
public Double asDouble() {
return isMissing() || isNull() || !data.isNumber() ? null : data.asDouble();
}
@Override
public String asString() {
return isMissing() || isNull() || !data.isTextual() ? null : data.asText();
}
@Override
public Date asDate() {
if (isMissing() || isNull() || !data.canConvertToLong()) {
return null;
}
long seconds = data.asLong();
return new Date(seconds * 1000);
}
@Override
public Instant asInstant() {
if (isMissing() || isNull() || !data.canConvertToLong()) {
return null;
}
long seconds = data.asLong();
return Instant.ofEpochSecond(seconds);
}
@Override
@SuppressWarnings("unchecked")
public <T> T[] asArray(Class<T> clazz) throws JWTDecodeException {
if (isMissing() || isNull() || !data.isArray()) {
return null;
}
T[] arr = (T[]) Array.newInstance(clazz, data.size());
for (int i = 0; i < data.size(); i++) {
try {
arr[i] = codec.treeToValue(data.get(i), clazz);
} catch (JsonProcessingException e) {
throw new JWTDecodeException("Couldn't map the Claim's array contents to " + clazz.getSimpleName(), e);
}
}
return arr;
}
@Override
public <T> List<T> asList(Class<T> clazz) throws JWTDecodeException {
if (isMissing() || isNull() || !data.isArray()) {
return null;
}
List<T> list = new ArrayList<>();
for (int i = 0; i < data.size(); i++) {
try {
list.add(codec.treeToValue(data.get(i), clazz));
} catch (JsonProcessingException e) {
throw new JWTDecodeException("Couldn't map the Claim's array contents to " + clazz.getSimpleName(), e);
}
}
return list;
}
@Override
public Map<String, Object> asMap() throws JWTDecodeException {
if (isMissing() || isNull() || !data.isObject()) {
return null;
}
TypeReference<Map<String, Object>> mapType = new TypeReference<Map<String, Object>>() {
};
try (JsonParser parser = codec.treeAsTokens(data)) {
return parser.readValueAs(mapType);
} catch (IOException e) {
throw new JWTDecodeException("Couldn't map the Claim value to Map", e);
}
}
@Override
public <T> T as(Class<T> clazz) throws JWTDecodeException {
try {
if (isMissing() || isNull()) {
return null;
}
return codec.treeToValue(data, clazz);
} catch (JsonProcessingException e) {
throw new JWTDecodeException("Couldn't map the Claim value to " + clazz.getSimpleName(), e);
}
}
@Override
public boolean isNull() {
return !isMissing() && data.isNull();
}
@Override
public boolean isMissing() {
return data == null || data.isMissingNode();
}
@Override
public String toString() {
if (isMissing()) {
return "Missing claim";
} else if (isNull()) {
return "Null claim";
}
return data.toString();
}
/**
* Helper method to extract a Claim from the given JsonNode tree.
*
* @param claimName the Claim to search for.
* @param tree the JsonNode tree to search the Claim in.
* @param objectCodec the object codec in use for deserialization
* @return a valid non-null Claim.
*/
static Claim extractClaim(String claimName, Map<String, JsonNode> tree, ObjectCodec objectCodec) {
JsonNode node = tree.get(claimName);
return claimFromNode(node, objectCodec);
}
/**
* Helper method to create a Claim representation from the given JsonNode.
*
* @param node the JsonNode to convert into a Claim.
* @param objectCodec the object codec in use for deserialization
* @return a valid Claim instance. If the node is null or missing, a NullClaim will be returned.
*/
static Claim claimFromNode(JsonNode node, ObjectCodec objectCodec) {
return new JsonNodeClaim(node, objectCodec);
}
}

View File

@@ -1,12 +0,0 @@
package com.auth0.jwt.impl;
import java.util.Map;
/**
* Holds the payload claims when serializing a JWT.
*/
public final class PayloadClaimsHolder extends ClaimsHolder {
public PayloadClaimsHolder(Map<String, Object> claims) {
super(claims);
}
}

View File

@@ -1,91 +0,0 @@
package com.auth0.jwt.impl;
import com.auth0.jwt.RegisteredClaims;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.Payload;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.time.Instant;
import java.util.*;
/**
* Jackson deserializer implementation for converting from JWT Payload parts.
* <p>
* This class is thread-safe.
*
* @see JWTParser
*/
class PayloadDeserializer extends StdDeserializer<Payload> {
PayloadDeserializer() {
super(Payload.class);
}
@Override
public Payload deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
Map<String, JsonNode> tree = p.getCodec().readValue(p, new TypeReference<Map<String, JsonNode>>() {
});
if (tree == null) {
throw new JWTDecodeException("Parsing the Payload's JSON resulted on a Null map");
}
String issuer = getString(tree, RegisteredClaims.ISSUER);
String subject = getString(tree, RegisteredClaims.SUBJECT);
List<String> audience = getStringOrArray(p.getCodec(), tree, RegisteredClaims.AUDIENCE);
Instant expiresAt = getInstantFromSeconds(tree, RegisteredClaims.EXPIRES_AT);
Instant notBefore = getInstantFromSeconds(tree, RegisteredClaims.NOT_BEFORE);
Instant issuedAt = getInstantFromSeconds(tree, RegisteredClaims.ISSUED_AT);
String jwtId = getString(tree, RegisteredClaims.JWT_ID);
return new PayloadImpl(issuer, subject, audience, expiresAt, notBefore, issuedAt, jwtId, tree, p.getCodec());
}
List<String> getStringOrArray(ObjectCodec codec, Map<String, JsonNode> tree, String claimName)
throws JWTDecodeException {
JsonNode node = tree.get(claimName);
if (node == null || node.isNull() || !(node.isArray() || node.isTextual())) {
return null;
}
if (node.isTextual() && !node.asText().isEmpty()) {
return Collections.singletonList(node.asText());
}
List<String> list = new ArrayList<>(node.size());
for (int i = 0; i < node.size(); i++) {
try {
list.add(codec.treeToValue(node.get(i), String.class));
} catch (JsonProcessingException e) {
throw new JWTDecodeException("Couldn't map the Claim's array contents to String", e);
}
}
return list;
}
Instant getInstantFromSeconds(Map<String, JsonNode> tree, String claimName) {
JsonNode node = tree.get(claimName);
if (node == null || node.isNull()) {
return null;
}
if (!node.canConvertToLong()) {
throw new JWTDecodeException(
String.format("The claim '%s' contained a non-numeric date value.", claimName));
}
return Instant.ofEpochSecond(node.asLong());
}
String getString(Map<String, JsonNode> tree, String claimName) {
JsonNode node = tree.get(claimName);
if (node == null || node.isNull()) {
return null;
}
return node.asText(null);
}
}

View File

@@ -1,129 +0,0 @@
package com.auth0.jwt.impl;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.Payload;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.Serializable;
import java.time.Instant;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.auth0.jwt.impl.JsonNodeClaim.extractClaim;
/**
* Decoder of string JSON Web Tokens into their POJO representations.
* <p>
* This class is thread-safe.
*
* @see Payload
*/
class PayloadImpl implements Payload, Serializable {
private static final long serialVersionUID = 1659021498824562311L;
private final String issuer;
private final String subject;
private final List<String> audience;
private final Instant expiresAt;
private final Instant notBefore;
private final Instant issuedAt;
private final String jwtId;
private final Map<String, JsonNode> tree;
private final ObjectCodec objectCodec;
PayloadImpl(
String issuer,
String subject,
List<String> audience,
Instant expiresAt,
Instant notBefore,
Instant issuedAt,
String jwtId,
Map<String, JsonNode> tree,
ObjectCodec objectCodec
) {
this.issuer = issuer;
this.subject = subject;
this.audience = audience != null ? Collections.unmodifiableList(audience) : null;
this.expiresAt = expiresAt;
this.notBefore = notBefore;
this.issuedAt = issuedAt;
this.jwtId = jwtId;
this.tree = tree != null ? Collections.unmodifiableMap(tree) : Collections.emptyMap();
this.objectCodec = objectCodec;
}
Map<String, JsonNode> getTree() {
return tree;
}
@Override
public String getIssuer() {
return issuer;
}
@Override
public String getSubject() {
return subject;
}
@Override
public List<String> getAudience() {
return audience;
}
@Override
public Date getExpiresAt() {
return (expiresAt != null) ? Date.from(expiresAt) : null;
}
@Override
public Instant getExpiresAtAsInstant() {
return expiresAt;
}
@Override
public Date getIssuedAt() {
return (issuedAt != null) ? Date.from(issuedAt) : null;
}
@Override
public Instant getIssuedAtAsInstant() {
return issuedAt;
}
@Override
public Date getNotBefore() {
return (notBefore != null) ? Date.from(notBefore) : null;
}
@Override
public Instant getNotBeforeAsInstant() {
return notBefore;
}
@Override
public String getId() {
return jwtId;
}
@Override
public Claim getClaim(String name) {
return extractClaim(name, tree, objectCodec);
}
@Override
public Map<String, Claim> getClaims() {
Map<String, Claim> claims = new HashMap<>(tree.size() * 2);
for (String name : tree.keySet()) {
claims.put(name, extractClaim(name, tree, objectCodec));
}
return Collections.unmodifiableMap(claims);
}
}

View File

@@ -1,66 +0,0 @@
package com.auth0.jwt.impl;
import com.auth0.jwt.RegisteredClaims;
import com.fasterxml.jackson.core.JsonGenerator;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* Jackson serializer implementation for converting into JWT Payload parts.
* <p>
* This class is thread-safe.
*
* @see com.auth0.jwt.JWTCreator
*/
public class PayloadSerializer extends ClaimsSerializer<PayloadClaimsHolder> {
public PayloadSerializer() {
super(PayloadClaimsHolder.class);
}
@Override
protected void writeClaim(Map.Entry<String, Object> entry, JsonGenerator gen) throws IOException {
if (RegisteredClaims.AUDIENCE.equals(entry.getKey())) {
writeAudience(gen, entry);
} else {
super.writeClaim(entry, gen);
}
}
/**
* Audience may be a list of strings or a single string. This is needed to properly handle the aud claim when
* added with the {@linkplain com.auth0.jwt.JWTCreator.Builder#withPayload(Map)} method.
*/
private void writeAudience(JsonGenerator gen, Map.Entry<String, Object> e) throws IOException {
if (e.getValue() instanceof String) {
gen.writeFieldName(e.getKey());
gen.writeString((String) e.getValue());
} else {
List<String> audArray = new ArrayList<>();
if (e.getValue() instanceof String[]) {
audArray = Arrays.asList((String[]) e.getValue());
} else if (e.getValue() instanceof List) {
List<?> audList = (List<?>) e.getValue();
for (Object aud : audList) {
if (aud instanceof String) {
audArray.add((String) aud);
}
}
}
if (audArray.size() == 1) {
gen.writeFieldName(e.getKey());
gen.writeString(audArray.get(0));
} else if (audArray.size() > 1) {
gen.writeFieldName(e.getKey());
gen.writeStartArray();
for (String aud : audArray) {
gen.writeString(aud);
}
gen.writeEndArray();
}
}
}
}

View File

@@ -1,7 +0,0 @@
/**
* Contains parts of the <b>internal</b> implementation of this library.
*
* <p><b>Do not use any of the classes in this package.</b> They might be removed
* or changed at any point without prior warning.
*/
package com.auth0.jwt.impl;

View File

@@ -1,131 +0,0 @@
package com.auth0.jwt.interfaces;
import com.auth0.jwt.exceptions.JWTDecodeException;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* The Claim class holds the value in a generic way so that it can be recovered in many representations.
*/
public interface Claim {
/**
* Whether this Claim has a null value or not.
* If the claim is not present, it will return false hence checking {@link Claim#isMissing} is advised as well
*
* @return whether this Claim has a null value or not.
*/
boolean isNull();
/**
* Can be used to verify whether the Claim is found or not.
* This will be true even if the Claim has {@code null} value associated to it.
*
* @return whether this Claim is present or not
*/
boolean isMissing();
/**
* Get this Claim as a Boolean.
* If the value isn't of type Boolean or it can't be converted to a Boolean, {@code null} will be returned.
*
* @return the value as a Boolean or null.
*/
Boolean asBoolean();
/**
* Get this Claim as an Integer.
* If the value isn't of type Integer or it can't be converted to an Integer, {@code null} will be returned.
*
* @return the value as an Integer or null.
*/
Integer asInt();
/**
* Get this Claim as an Long.
* If the value isn't of type Long or it can't be converted to a Long, {@code null} will be returned.
*
* @return the value as an Long or null.
*/
Long asLong();
/**
* Get this Claim as a Double.
* If the value isn't of type Double or it can't be converted to a Double, {@code null} will be returned.
*
* @return the value as a Double or null.
*/
Double asDouble();
/**
* Get this Claim as a String.
* If the value isn't of type String, {@code null} will be returned. For a String representation of non-textual
* claim types, clients can call {@code toString()}.
*
* @return the value as a String or null if the underlying value is not a string.
*/
String asString();
/**
* Get this Claim as a Date.
* If the value can't be converted to a Date, {@code null} will be returned.
*
* @return the value as a Date or null.
*/
Date asDate();
/**
* Get this Claim as an Instant.
* If the value can't be converted to an Instant, {@code null} will be returned.
*
* @return the value as a Date or null.
*/
default Instant asInstant() {
Date date = asDate();
return date != null ? date.toInstant() : null;
}
/**
* Get this Claim as an Array of type T.
* If the value isn't an Array, {@code null} will be returned.
*
* @param <T> type
* @param clazz the type class
* @return the value as an Array or null.
* @throws JWTDecodeException if the values inside the Array can't be converted to a class T.
*/
<T> T[] asArray(Class<T> clazz) throws JWTDecodeException;
/**
* Get this Claim as a List of type T.
* If the value isn't an Array, {@code null} will be returned.
*
* @param <T> type
* @param clazz the type class
* @return the value as a List or null.
* @throws JWTDecodeException if the values inside the List can't be converted to a class T.
*/
<T> List<T> asList(Class<T> clazz) throws JWTDecodeException;
/**
* Get this Claim as a generic Map of values.
*
* @return the value as instance of Map.
* @throws JWTDecodeException if the value can't be converted to a Map.
*/
Map<String, Object> asMap() throws JWTDecodeException;
/**
* Get this Claim as a custom type T.
* This method will return null if {@link Claim#isMissing()} or {@link Claim#isNull()} is true
*
* @param <T> type
* @param clazz the type class
* @return the value as instance of T.
* @throws JWTDecodeException if the value can't be converted to a class T.
*/
<T> T as(Class<T> clazz) throws JWTDecodeException;
}

View File

@@ -1,37 +0,0 @@
package com.auth0.jwt.interfaces;
/**
* Class that represents a Json Web Token that was decoded from it's string representation.
*/
public interface DecodedJWT extends Payload, Header {
/**
* Getter for the String Token used to create this JWT instance.
*
* @return the String Token.
*/
String getToken();
/**
* Getter for the Header contained in the JWT as a Base64 encoded String.
* This represents the first part of the token.
*
* @return the Header of the JWT.
*/
String getHeader();
/**
* Getter for the Payload contained in the JWT as a Base64 encoded String.
* This represents the second part of the token.
*
* @return the Payload of the JWT.
*/
String getPayload();
/**
* Getter for the Signature contained in the JWT as a Base64 encoded String.
* This represents the third part of the token.
*
* @return the Signature of the JWT.
*/
String getSignature();
}

View File

@@ -1,10 +0,0 @@
package com.auth0.jwt.interfaces;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
/**
* Elliptic Curve (EC) Public/Private Key provider.
*/
public interface ECDSAKeyProvider extends KeyProvider<ECPublicKey, ECPrivateKey> {
}

View File

@@ -1,44 +0,0 @@
package com.auth0.jwt.interfaces;
/**
* The Header class represents the 1st part of the JWT, where the Header value is held.
*/
public interface Header {
/**
* Getter for the Algorithm "alg" claim defined in the JWT's Header. If the claim is missing it will return null.
*
* @return the Algorithm defined or null.
*/
String getAlgorithm();
/**
* Getter for the Type "typ" claim defined in the JWT's Header. If the claim is missing it will return null.
*
* @return the Type defined or null.
*/
String getType();
/**
* Getter for the Content Type "cty" claim defined in the JWT's Header. If the claim is missing it will return null.
*
* @return the Content Type defined or null.
*/
String getContentType();
/**
* Get the value of the "kid" claim, or null if it's not available.
*
* @return the Key ID value or null.
*/
String getKeyId();
/**
* Get a Private Claim given it's name. If the Claim wasn't specified in the Header, a 'null claim' will be
* returned. All the methods of that claim will return {@code null}.
*
* @param name the name of the Claim to retrieve.
* @return a non-null Claim.
*/
Claim getHeaderClaim(String name);
}

View File

@@ -1,28 +0,0 @@
package com.auth0.jwt.interfaces;
import com.auth0.jwt.exceptions.JWTDecodeException;
/**
* The JWTPartsParser class defines which parts of the JWT should be converted
* to its specific Object representation instance.
*/
public interface JWTPartsParser {
/**
* Parses the given JSON into a {@link Payload} instance.
*
* @param json the content of the Payload in a JSON representation.
* @return the Payload.
* @throws JWTDecodeException if the json doesn't have a proper JSON format.
*/
Payload parsePayload(String json) throws JWTDecodeException;
/**
* Parses the given JSON into a {@link Header} instance.
*
* @param json the content of the Header in a JSON representation.
* @return the Header.
* @throws JWTDecodeException if the json doesn't have a proper JSON format.
*/
Header parseHeader(String json) throws JWTDecodeException;
}

View File

@@ -1,40 +0,0 @@
package com.auth0.jwt.interfaces;
import com.auth0.jwt.exceptions.JWTVerificationException;
/**
* Used to verify the JWT for its signature and claims. Implementations must be thread-safe. Instances are created
* using {@link Verification}.
*
* <pre>
* try {
* JWTVerifier verifier = JWTVerifier.init(Algorithm.RSA256(publicKey, privateKey)
* .withIssuer("auth0")
* .build();
* DecodedJWT jwt = verifier.verify("token");
* } catch (JWTVerificationException e) {
* // invalid signature or claims
* }
* </pre>
*/
public interface JWTVerifier {
/**
* Performs the verification against the given Token.
*
* @param token to verify.
* @return a verified and decoded JWT.
* @throws JWTVerificationException if any of the verification steps fail
*/
DecodedJWT verify(String token) throws JWTVerificationException;
/**
* Performs the verification against the given {@link DecodedJWT}.
*
* @param jwt to verify.
* @return a verified and decoded JWT.
* @throws JWTVerificationException if any of the verification steps fail
*/
DecodedJWT verify(DecodedJWT jwt) throws JWTVerificationException;
}

View File

@@ -1,38 +0,0 @@
package com.auth0.jwt.interfaces;
import java.security.PrivateKey;
import java.security.PublicKey;
/**
* Generic Public/Private Key provider.
* While implementing, ensure the Private Key and Private Key ID doesn't change in between signing a token.
*
* @param <U> the class that represents the Public Key
* @param <R> the class that represents the Private Key
*/
interface KeyProvider<U extends PublicKey, R extends PrivateKey> {
/**
* Getter for the Public Key instance with the given Id. Used to verify the signature on the JWT verification stage.
*
* @param keyId the Key Id specified in the Token's Header or null if none is available.
* Provides a hint on which Public Key to use to verify the token's signature.
* @return the Public Key instance
*/
U getPublicKeyById(String keyId);
/**
* Getter for the Private Key instance. Used to sign the content on the JWT signing stage.
*
* @return the Private Key instance
*/
R getPrivateKey();
/**
* Getter for the Id of the Private Key used to sign the tokens.
* This represents the `kid` claim and will be placed in the Header.
*
* @return the Key Id that identifies the Private Key or null if it's not specified.
*/
String getPrivateKeyId();
}

View File

@@ -1,104 +0,0 @@
package com.auth0.jwt.interfaces;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* The Payload class represents the 2nd part of the JWT, where the Payload value is held.
*/
public interface Payload {
/**
* Get the value of the "iss" claim, or null if it's not available.
*
* @return the Issuer value or null.
*/
String getIssuer();
/**
* Get the value of the "sub" claim, or null if it's not available.
*
* @return the Subject value or null.
*/
String getSubject();
/**
* Get the value of the "aud" claim, or null if it's not available.
*
* @return the Audience value or null.
*/
List<String> getAudience();
/**
* Get the value of the "exp" claim, or null if it's not available.
*
* @return the Expiration Time value or null.
*/
Date getExpiresAt();
/**
* Get the value of the "exp" claim as an {@linkplain Instant}, or null if it's not available.
*
* @return the Expiration Time value or null.
*/
default Instant getExpiresAtAsInstant() {
return getExpiresAt() != null ? getExpiresAt().toInstant() : null;
}
/**
* Get the value of the "nbf" claim, or null if it's not available.
*
* @return the Not Before value or null.
*/
Date getNotBefore();
/**
* Get the value of the "nbf" claim as an {@linkplain Instant}, or null if it's not available.
*
* @return the Not Before value or null.
*/
default Instant getNotBeforeAsInstant() {
return getNotBefore() != null ? getNotBefore().toInstant() : null;
}
/**
* Get the value of the "iat" claim, or null if it's not available.
*
* @return the Issued At value or null.
*/
Date getIssuedAt();
/**
* Get the value of the "iat" claim as an {@linkplain Instant}, or null if it's not available.
*
* @return the Issued At value or null.
*/
default Instant getIssuedAtAsInstant() {
return getIssuedAt() != null ? getIssuedAt().toInstant() : null;
}
/**
* Get the value of the "jti" claim, or null if it's not available.
*
* @return the JWT ID value or null.
*/
String getId();
/**
* Get a Claim given its name. If the Claim wasn't specified in the Payload, a 'null claim'
* will be returned. All the methods of that claim will return {@code null}.
*
* @param name the name of the Claim to retrieve.
* @return a non-null Claim.
*/
Claim getClaim(String name);
/**
* Get the Claims defined in the Token.
*
* @return a non-null Map containing the Claims defined in the Token.
*/
Map<String, Claim> getClaims();
}

View File

@@ -1,10 +0,0 @@
package com.auth0.jwt.interfaces;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
/**
* RSA Public/Private Key provider.
*/
public interface RSAKeyProvider extends KeyProvider<RSAPublicKey, RSAPrivateKey> {
}

View File

@@ -1,267 +0,0 @@
package com.auth0.jwt.interfaces;
import com.auth0.jwt.JWTVerifier;
import java.time.Instant;
import java.util.Date;
import java.util.function.BiPredicate;
/**
* Constructs and holds the checks required for a JWT to be considered valid. Note that implementations are
* <strong>not</strong> thread-safe. Once built by calling {@link #build()}, the resulting
* {@link com.auth0.jwt.interfaces.JWTVerifier} is thread-safe.
*/
public interface Verification {
/**
* Verifies whether the JWT contains an Issuer ("iss") claim that equals to the value provided.
* This check is case-sensitive.
*
* @param issuer the required Issuer value.
* @return this same Verification instance.
*/
default Verification withIssuer(String issuer) {
return withIssuer(new String[]{issuer});
}
/**
* Verifies whether the JWT contains an Issuer ("iss") claim that contains all the values provided.
* This check is case-sensitive. An empty array is considered as a {@code null}.
*
* @param issuer the required Issuer value. If multiple values are given, the claim must at least match one of them
* @return this same Verification instance.
*/
Verification withIssuer(String... issuer);
/**
* Verifies whether the JWT contains a Subject ("sub") claim that equals to the value provided.
* This check is case-sensitive.
*
* @param subject the required Subject value
* @return this same Verification instance.
*/
Verification withSubject(String subject);
/**
* Verifies whether the JWT contains an Audience ("aud") claim that contains all the values provided.
* This check is case-sensitive. An empty array is considered as a {@code null}.
*
* @param audience the required Audience value
* @return this same Verification instance.
*/
Verification withAudience(String... audience);
/**
* Verifies whether the JWT contains an Audience ("aud") claim contain at least one of the specified audiences.
* This check is case-sensitive. An empty array is considered as a {@code null}.
*
* @param audience the required Audience value for which the "aud" claim must contain at least one value.
* @return this same Verification instance.
*/
Verification withAnyOfAudience(String... audience);
/**
* Define the default window in seconds in which the Not Before, Issued At and Expires At Claims
* will still be valid. Setting a specific leeway value on a given Claim will override this value for that Claim.
*
* @param leeway the window in seconds in which the Not Before, Issued At and Expires At Claims will still be valid.
* @return this same Verification instance.
* @throws IllegalArgumentException if leeway is negative.
*/
Verification acceptLeeway(long leeway) throws IllegalArgumentException;
/**
* Set a specific leeway window in seconds in which the Expires At ("exp") Claim will still be valid.
* Expiration Date is always verified when the value is present.
* This method overrides the value set with acceptLeeway
*
* @param leeway the window in seconds in which the Expires At Claim will still be valid.
* @return this same Verification instance.
* @throws IllegalArgumentException if leeway is negative.
*/
Verification acceptExpiresAt(long leeway) throws IllegalArgumentException;
/**
* Set a specific leeway window in seconds in which the Not Before ("nbf") Claim will still be valid.
* Not Before Date is always verified when the value is present.
* This method overrides the value set with acceptLeeway
*
* @param leeway the window in seconds in which the Not Before Claim will still be valid.
* @return this same Verification instance.
* @throws IllegalArgumentException if leeway is negative.
*/
Verification acceptNotBefore(long leeway) throws IllegalArgumentException;
/**
* Set a specific leeway window in seconds in which the Issued At ("iat") Claim will still be valid.
* This method overrides the value set with {@link #acceptLeeway(long)}.
* By default, the Issued At claim is always verified when the value is present,
* unless disabled with {@link #ignoreIssuedAt()}.
* If Issued At verification has been disabled, no verification of the Issued At claim will be performed,
* and this method has no effect.
*
* @param leeway the window in seconds in which the Issued At Claim will still be valid.
* @return this same Verification instance.
* @throws IllegalArgumentException if leeway is negative.
*/
Verification acceptIssuedAt(long leeway) throws IllegalArgumentException;
/**
* Verifies whether the JWT contains a JWT ID ("jti") claim that equals to the value provided.
* This check is case-sensitive.
*
* @param jwtId the required ID value
* @return this same Verification instance.
*/
Verification withJWTId(String jwtId);
/**
* Verifies whether the claim is present in the JWT, with any value including {@code null}.
*
* @param name the Claim's name.
* @return this same Verification instance
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withClaimPresence(String name) throws IllegalArgumentException;
/**
* Verifies whether the claim is present with a {@code null} value.
*
* @param name the Claim's name.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withNullClaim(String name) throws IllegalArgumentException;
/**
* Verifies whether the claim is equal to the given Boolean value.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withClaim(String name, Boolean value) throws IllegalArgumentException;
/**
* Verifies whether the claim is equal to the given Integer value.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withClaim(String name, Integer value) throws IllegalArgumentException;
/**
* Verifies whether the claim is equal to the given Long value.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withClaim(String name, Long value) throws IllegalArgumentException;
/**
* Verifies whether the claim is equal to the given Integer value.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withClaim(String name, Double value) throws IllegalArgumentException;
/**
* Verifies whether the claim is equal to the given String value.
* This check is case-sensitive.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withClaim(String name, String value) throws IllegalArgumentException;
/**
* Verifies whether the claim is equal to the given Date value.
* Note that date-time claims are serialized as seconds since the epoch;
* when verifying date-time claim value, any time units more granular than seconds will not be considered.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withClaim(String name, Date value) throws IllegalArgumentException;
/**
* Verifies whether the claim is equal to the given Instant value.
* Note that date-time claims are serialized as seconds since the epoch;
* when verifying a date-time claim value, any time units more granular than seconds will not be considered.
*
* @param name the Claim's name.
* @param value the Claim's value.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
default Verification withClaim(String name, Instant value) throws IllegalArgumentException {
return withClaim(name, value != null ? Date.from(value) : null);
}
/**
* Executes the predicate provided and the validates the JWT if the predicate returns true.
*
* @param name the Claim's name
* @param predicate the predicate check to be done.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withClaim(String name, BiPredicate<Claim, DecodedJWT> predicate) throws IllegalArgumentException;
/**
* Verifies whether the claim contain at least the given String items.
*
* @param name the Claim's name.
* @param items the items the Claim must contain.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withArrayClaim(String name, String... items) throws IllegalArgumentException;
/**
* Verifies whether the claim contain at least the given Integer items.
*
* @param name the Claim's name.
* @param items the items the Claim must contain.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withArrayClaim(String name, Integer... items) throws IllegalArgumentException;
/**
* Verifies whether the claim contain at least the given Long items.
*
* @param name the Claim's name.
* @param items the items the Claim must contain.
* @return this same Verification instance.
* @throws IllegalArgumentException if the name is {@code null}.
*/
Verification withArrayClaim(String name, Long ... items) throws IllegalArgumentException;
/**
* Skip the Issued At ("iat") claim verification. By default, the verification is performed.
*
* @return this same Verification instance.
*/
Verification ignoreIssuedAt();
/**
* Creates a new and reusable instance of the JWTVerifier with the configuration already provided.
*
* @return a new {@link com.auth0.jwt.interfaces.JWTVerifier} instance.
*/
JWTVerifier build();
}

View File

@@ -1,26 +0,0 @@
// Generated automatically from javax.crypto.KeyGenerator for testing purposes
package javax.crypto;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.KeyGeneratorSpi;
import javax.crypto.SecretKey;
public class KeyGenerator
{
protected KeyGenerator() {}
protected KeyGenerator(KeyGeneratorSpi p0, Provider p1, String p2){}
public final Provider getProvider(){ return null; }
public final SecretKey generateKey(){ return null; }
public final String getAlgorithm(){ return null; }
public final void init(AlgorithmParameterSpec p0){}
public final void init(AlgorithmParameterSpec p0, SecureRandom p1){}
public final void init(SecureRandom p0){}
public final void init(int p0){}
public final void init(int p0, SecureRandom p1){}
public static KeyGenerator getInstance(String p0){ return null; }
public static KeyGenerator getInstance(String p0, Provider p1){ return null; }
public static KeyGenerator getInstance(String p0, String p1){ return null; }
}

View File

@@ -1,16 +0,0 @@
// Generated automatically from javax.crypto.KeyGeneratorSpi for testing purposes
package javax.crypto;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.SecretKey;
abstract public class KeyGeneratorSpi
{
protected abstract SecretKey engineGenerateKey();
protected abstract void engineInit(AlgorithmParameterSpec p0, SecureRandom p1);
protected abstract void engineInit(SecureRandom p0);
protected abstract void engineInit(int p0, SecureRandom p1);
public KeyGeneratorSpi(){}
}

View File

@@ -1,11 +0,0 @@
// Generated automatically from javax.crypto.SecretKey for testing purposes
package javax.crypto;
import java.security.Key;
import javax.security.auth.Destroyable;
public interface SecretKey extends Destroyable, Key
{
static long serialVersionUID = 0;
}

View File

@@ -1,10 +0,0 @@
// Generated automatically from javax.security.auth.Destroyable for testing purposes
package javax.security.auth;
public interface Destroyable
{
default boolean isDestroyed(){ return false; }
default void destroy(){}
}

View File

@@ -1,31 +0,0 @@
// Generated automatically from javax.servlet.AsyncContext for testing purposes
package javax.servlet;
import javax.servlet.AsyncListener;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public interface AsyncContext
{
<T extends AsyncListener> T createListener(java.lang.Class<T> p0);
ServletRequest getRequest();
ServletResponse getResponse();
boolean hasOriginalRequestAndResponse();
long getTimeout();
static String ASYNC_CONTEXT_PATH = null;
static String ASYNC_MAPPING = null;
static String ASYNC_PATH_INFO = null;
static String ASYNC_QUERY_STRING = null;
static String ASYNC_REQUEST_URI = null;
static String ASYNC_SERVLET_PATH = null;
void addListener(AsyncListener p0);
void addListener(AsyncListener p0, ServletRequest p1, ServletResponse p2);
void complete();
void dispatch();
void dispatch(ServletContext p0, String p1);
void dispatch(String p0);
void setTimeout(long p0);
void start(Runnable p0);
}

View File

@@ -1,20 +0,0 @@
// Generated automatically from javax.servlet.AsyncEvent for testing purposes
package javax.servlet;
import javax.servlet.AsyncContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class AsyncEvent
{
protected AsyncEvent() {}
public AsyncContext getAsyncContext(){ return null; }
public AsyncEvent(AsyncContext p0){}
public AsyncEvent(AsyncContext p0, ServletRequest p1, ServletResponse p2){}
public AsyncEvent(AsyncContext p0, ServletRequest p1, ServletResponse p2, Throwable p3){}
public AsyncEvent(AsyncContext p0, Throwable p1){}
public ServletRequest getSuppliedRequest(){ return null; }
public ServletResponse getSuppliedResponse(){ return null; }
public Throwable getThrowable(){ return null; }
}

View File

@@ -1,14 +0,0 @@
// Generated automatically from javax.servlet.AsyncListener for testing purposes
package javax.servlet;
import java.util.EventListener;
import javax.servlet.AsyncEvent;
public interface AsyncListener extends EventListener
{
void onComplete(AsyncEvent p0);
void onError(AsyncEvent p0);
void onStartAsync(AsyncEvent p0);
void onTimeout(AsyncEvent p0);
}

View File

@@ -1,10 +0,0 @@
// Generated automatically from javax.servlet.DispatcherType for testing purposes
package javax.servlet;
public enum DispatcherType
{
ASYNC, ERROR, FORWARD, INCLUDE, REQUEST;
private DispatcherType() {}
}

View File

@@ -1,15 +0,0 @@
// Generated automatically from javax.servlet.Filter for testing purposes
package javax.servlet;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public interface Filter
{
default void destroy(){}
default void init(FilterConfig p0){}
void doFilter(ServletRequest p0, ServletResponse p1, FilterChain p2);
}

View File

@@ -1,11 +0,0 @@
// Generated automatically from javax.servlet.FilterChain for testing purposes
package javax.servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public interface FilterChain
{
void doFilter(ServletRequest p0, ServletResponse p1);
}

View File

@@ -1,14 +0,0 @@
// Generated automatically from javax.servlet.FilterConfig for testing purposes
package javax.servlet;
import java.util.Enumeration;
import javax.servlet.ServletContext;
public interface FilterConfig
{
Enumeration<String> getInitParameterNames();
ServletContext getServletContext();
String getFilterName();
String getInitParameter(String p0);
}

View File

@@ -1,19 +0,0 @@
// Generated automatically from javax.servlet.FilterRegistration for testing purposes
package javax.servlet;
import java.util.Collection;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.Registration;
public interface FilterRegistration extends Registration
{
Collection<String> getServletNameMappings();
Collection<String> getUrlPatternMappings();
static public interface Dynamic extends FilterRegistration, Registration.Dynamic
{
}
void addMappingForServletNames(EnumSet<DispatcherType> p0, boolean p1, String... p2);
void addMappingForUrlPatterns(EnumSet<DispatcherType> p0, boolean p1, String... p2);
}

View File

@@ -1,28 +0,0 @@
// Generated automatically from javax.servlet.GenericServlet for testing purposes
package javax.servlet;
import java.io.Serializable;
import java.util.Enumeration;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
abstract public class GenericServlet implements Serializable, Servlet, ServletConfig
{
public Enumeration<String> getInitParameterNames(){ return null; }
public GenericServlet(){}
public ServletConfig getServletConfig(){ return null; }
public ServletContext getServletContext(){ return null; }
public String getInitParameter(String p0){ return null; }
public String getServletInfo(){ return null; }
public String getServletName(){ return null; }
public abstract void service(ServletRequest p0, ServletResponse p1);
public void destroy(){}
public void init(){}
public void init(ServletConfig p0){}
public void log(String p0){}
public void log(String p0, Throwable p1){}
}

View File

@@ -1,16 +0,0 @@
// Generated automatically from javax.servlet.HttpConstraintElement for testing purposes
package javax.servlet;
import javax.servlet.annotation.ServletSecurity;
public class HttpConstraintElement
{
public HttpConstraintElement(){}
public HttpConstraintElement(ServletSecurity.EmptyRoleSemantic p0){}
public HttpConstraintElement(ServletSecurity.EmptyRoleSemantic p0, ServletSecurity.TransportGuarantee p1, String... p2){}
public HttpConstraintElement(ServletSecurity.TransportGuarantee p0, String... p1){}
public ServletSecurity.EmptyRoleSemantic getEmptyRoleSemantic(){ return null; }
public ServletSecurity.TransportGuarantee getTransportGuarantee(){ return null; }
public String[] getRolesAllowed(){ return null; }
}

View File

@@ -1,13 +0,0 @@
// Generated automatically from javax.servlet.HttpMethodConstraintElement for testing purposes
package javax.servlet;
import javax.servlet.HttpConstraintElement;
public class HttpMethodConstraintElement extends HttpConstraintElement
{
protected HttpMethodConstraintElement() {}
public HttpMethodConstraintElement(String p0){}
public HttpMethodConstraintElement(String p0, HttpConstraintElement p1){}
public String getMethodName(){ return null; }
}

View File

@@ -1,17 +0,0 @@
// Generated automatically from javax.servlet.MultipartConfigElement for testing purposes
package javax.servlet;
import javax.servlet.annotation.MultipartConfig;
public class MultipartConfigElement
{
protected MultipartConfigElement() {}
public MultipartConfigElement(MultipartConfig p0){}
public MultipartConfigElement(String p0){}
public MultipartConfigElement(String p0, long p1, long p2, int p3){}
public String getLocation(){ return null; }
public int getFileSizeThreshold(){ return 0; }
public long getMaxFileSize(){ return 0; }
public long getMaxRequestSize(){ return 0; }
}

View File

@@ -1,12 +0,0 @@
// Generated automatically from javax.servlet.ReadListener for testing purposes
package javax.servlet;
import java.util.EventListener;
public interface ReadListener extends EventListener
{
void onAllDataRead();
void onDataAvailable();
void onError(Throwable p0);
}

View File

@@ -1,20 +0,0 @@
// Generated automatically from javax.servlet.Registration for testing purposes
package javax.servlet;
import java.util.Map;
import java.util.Set;
public interface Registration
{
Map<String, String> getInitParameters();
Set<String> setInitParameters(Map<String, String> p0);
String getClassName();
String getInitParameter(String p0);
String getName();
boolean setInitParameter(String p0, String p1);
static public interface Dynamic extends Registration
{
void setAsyncSupported(boolean p0);
}
}

View File

@@ -1,30 +0,0 @@
// Generated automatically from javax.servlet.RequestDispatcher for testing purposes
package javax.servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public interface RequestDispatcher
{
static String ERROR_EXCEPTION = null;
static String ERROR_EXCEPTION_TYPE = null;
static String ERROR_MESSAGE = null;
static String ERROR_REQUEST_URI = null;
static String ERROR_SERVLET_NAME = null;
static String ERROR_STATUS_CODE = null;
static String FORWARD_CONTEXT_PATH = null;
static String FORWARD_MAPPING = null;
static String FORWARD_PATH_INFO = null;
static String FORWARD_QUERY_STRING = null;
static String FORWARD_REQUEST_URI = null;
static String FORWARD_SERVLET_PATH = null;
static String INCLUDE_CONTEXT_PATH = null;
static String INCLUDE_MAPPING = null;
static String INCLUDE_PATH_INFO = null;
static String INCLUDE_QUERY_STRING = null;
static String INCLUDE_REQUEST_URI = null;
static String INCLUDE_SERVLET_PATH = null;
void forward(ServletRequest p0, ServletResponse p1);
void include(ServletRequest p0, ServletResponse p1);
}

View File

@@ -1,16 +0,0 @@
// Generated automatically from javax.servlet.Servlet for testing purposes
package javax.servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public interface Servlet
{
ServletConfig getServletConfig();
String getServletInfo();
void destroy();
void init(ServletConfig p0);
void service(ServletRequest p0, ServletResponse p1);
}

View File

@@ -1,14 +0,0 @@
// Generated automatically from javax.servlet.ServletConfig for testing purposes
package javax.servlet;
import java.util.Enumeration;
import javax.servlet.ServletContext;
public interface ServletConfig
{
Enumeration<String> getInitParameterNames();
ServletContext getServletContext();
String getInitParameter(String p0);
String getServletName();
}

View File

@@ -1,83 +0,0 @@
// Generated automatically from javax.servlet.ServletContext for testing purposes
package javax.servlet;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Map;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletRegistration;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.descriptor.JspConfigDescriptor;
public interface ServletContext
{
<T extends EventListener> T createListener(java.lang.Class<T> p0);
<T extends EventListener> void addListener(T p0);
<T extends Filter> T createFilter(java.lang.Class<T> p0);
<T extends Servlet> T createServlet(java.lang.Class<T> p0);
ClassLoader getClassLoader();
Enumeration<Servlet> getServlets();
Enumeration<String> getAttributeNames();
Enumeration<String> getInitParameterNames();
Enumeration<String> getServletNames();
FilterRegistration getFilterRegistration(String p0);
FilterRegistration.Dynamic addFilter(String p0, Class<? extends Filter> p1);
FilterRegistration.Dynamic addFilter(String p0, Filter p1);
FilterRegistration.Dynamic addFilter(String p0, String p1);
InputStream getResourceAsStream(String p0);
JspConfigDescriptor getJspConfigDescriptor();
Map<String, ? extends FilterRegistration> getFilterRegistrations();
Map<String, ? extends ServletRegistration> getServletRegistrations();
Object getAttribute(String p0);
RequestDispatcher getNamedDispatcher(String p0);
RequestDispatcher getRequestDispatcher(String p0);
Servlet getServlet(String p0);
ServletContext getContext(String p0);
ServletRegistration getServletRegistration(String p0);
ServletRegistration.Dynamic addJspFile(String p0, String p1);
ServletRegistration.Dynamic addServlet(String p0, Class<? extends Servlet> p1);
ServletRegistration.Dynamic addServlet(String p0, Servlet p1);
ServletRegistration.Dynamic addServlet(String p0, String p1);
SessionCookieConfig getSessionCookieConfig();
Set<SessionTrackingMode> getDefaultSessionTrackingModes();
Set<SessionTrackingMode> getEffectiveSessionTrackingModes();
Set<String> getResourcePaths(String p0);
String getContextPath();
String getInitParameter(String p0);
String getMimeType(String p0);
String getRealPath(String p0);
String getRequestCharacterEncoding();
String getResponseCharacterEncoding();
String getServerInfo();
String getServletContextName();
String getVirtualServerName();
URL getResource(String p0);
boolean setInitParameter(String p0, String p1);
int getEffectiveMajorVersion();
int getEffectiveMinorVersion();
int getMajorVersion();
int getMinorVersion();
int getSessionTimeout();
static String ORDERED_LIBS = null;
static String TEMPDIR = null;
void addListener(Class<? extends EventListener> p0);
void addListener(String p0);
void declareRoles(String... p0);
void log(Exception p0, String p1);
void log(String p0);
void log(String p0, Throwable p1);
void removeAttribute(String p0);
void setAttribute(String p0, Object p1);
void setRequestCharacterEncoding(String p0);
void setResponseCharacterEncoding(String p0);
void setSessionTimeout(int p0);
void setSessionTrackingModes(Set<SessionTrackingMode> p0);
}

View File

@@ -1,15 +0,0 @@
// Generated automatically from javax.servlet.ServletInputStream for testing purposes
package javax.servlet;
import java.io.InputStream;
import javax.servlet.ReadListener;
abstract public class ServletInputStream extends InputStream
{
protected ServletInputStream(){}
public abstract boolean isFinished();
public abstract boolean isReady();
public abstract void setReadListener(ReadListener p0);
public int readLine(byte[] p0, int p1, int p2){ return 0; }
}

View File

@@ -1,28 +0,0 @@
// Generated automatically from javax.servlet.ServletOutputStream for testing purposes
package javax.servlet;
import java.io.OutputStream;
import javax.servlet.WriteListener;
abstract public class ServletOutputStream extends OutputStream
{
protected ServletOutputStream(){}
public abstract boolean isReady();
public abstract void setWriteListener(WriteListener p0);
public void print(String p0){}
public void print(boolean p0){}
public void print(char p0){}
public void print(double p0){}
public void print(float p0){}
public void print(int p0){}
public void print(long p0){}
public void println(){}
public void println(String p0){}
public void println(boolean p0){}
public void println(char p0){}
public void println(double p0){}
public void println(float p0){}
public void println(int p0){}
public void println(long p0){}
}

View File

@@ -1,23 +0,0 @@
// Generated automatically from javax.servlet.ServletRegistration for testing purposes
package javax.servlet;
import java.util.Collection;
import java.util.Set;
import javax.servlet.MultipartConfigElement;
import javax.servlet.Registration;
import javax.servlet.ServletSecurityElement;
public interface ServletRegistration extends Registration
{
Collection<String> getMappings();
Set<String> addMapping(String... p0);
String getRunAsRole();
static public interface Dynamic extends Registration.Dynamic, ServletRegistration
{
Set<String> setServletSecurity(ServletSecurityElement p0);
void setLoadOnStartup(int p0);
void setMultipartConfig(MultipartConfigElement p0);
void setRunAsRole(String p0);
}
}

View File

@@ -1,55 +0,0 @@
// Generated automatically from javax.servlet.ServletRequest for testing purposes
package javax.servlet;
import java.io.BufferedReader;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletResponse;
public interface ServletRequest
{
AsyncContext getAsyncContext();
AsyncContext startAsync();
AsyncContext startAsync(ServletRequest p0, ServletResponse p1);
BufferedReader getReader();
DispatcherType getDispatcherType();
Enumeration<Locale> getLocales();
Enumeration<String> getAttributeNames();
Enumeration<String> getParameterNames();
Locale getLocale();
Map<String, String[]> getParameterMap();
Object getAttribute(String p0);
RequestDispatcher getRequestDispatcher(String p0);
ServletContext getServletContext();
ServletInputStream getInputStream();
String getCharacterEncoding();
String getContentType();
String getLocalAddr();
String getLocalName();
String getParameter(String p0);
String getProtocol();
String getRealPath(String p0);
String getRemoteAddr();
String getRemoteHost();
String getScheme();
String getServerName();
String[] getParameterValues(String p0);
boolean isAsyncStarted();
boolean isAsyncSupported();
boolean isSecure();
int getContentLength();
int getLocalPort();
int getRemotePort();
int getServerPort();
long getContentLengthLong();
void removeAttribute(String p0);
void setAttribute(String p0, Object p1);
void setCharacterEncoding(String p0);
}

View File

@@ -1,27 +0,0 @@
// Generated automatically from javax.servlet.ServletResponse for testing purposes
package javax.servlet;
import java.io.PrintWriter;
import java.util.Locale;
import javax.servlet.ServletOutputStream;
public interface ServletResponse
{
Locale getLocale();
PrintWriter getWriter();
ServletOutputStream getOutputStream();
String getCharacterEncoding();
String getContentType();
boolean isCommitted();
int getBufferSize();
void flushBuffer();
void reset();
void resetBuffer();
void setBufferSize(int p0);
void setCharacterEncoding(String p0);
void setContentLength(int p0);
void setContentLengthLong(long p0);
void setContentType(String p0);
void setLocale(Locale p0);
}

View File

@@ -1,19 +0,0 @@
// Generated automatically from javax.servlet.ServletSecurityElement for testing purposes
package javax.servlet;
import java.util.Collection;
import javax.servlet.HttpConstraintElement;
import javax.servlet.HttpMethodConstraintElement;
import javax.servlet.annotation.ServletSecurity;
public class ServletSecurityElement extends HttpConstraintElement
{
public Collection<HttpMethodConstraintElement> getHttpMethodConstraints(){ return null; }
public Collection<String> getMethodNames(){ return null; }
public ServletSecurityElement(){}
public ServletSecurityElement(Collection<HttpMethodConstraintElement> p0){}
public ServletSecurityElement(HttpConstraintElement p0){}
public ServletSecurityElement(HttpConstraintElement p0, Collection<HttpMethodConstraintElement> p1){}
public ServletSecurityElement(ServletSecurity p0){}
}

View File

@@ -1,22 +0,0 @@
// Generated automatically from javax.servlet.SessionCookieConfig for testing purposes
package javax.servlet;
public interface SessionCookieConfig
{
String getComment();
String getDomain();
String getName();
String getPath();
boolean isHttpOnly();
boolean isSecure();
int getMaxAge();
void setComment(String p0);
void setDomain(String p0);
void setHttpOnly(boolean p0);
void setMaxAge(int p0);
void setName(String p0);
void setPath(String p0);
void setSecure(boolean p0);
}

View File

@@ -1,10 +0,0 @@
// Generated automatically from javax.servlet.SessionTrackingMode for testing purposes
package javax.servlet;
public enum SessionTrackingMode
{
COOKIE, SSL, URL;
private SessionTrackingMode() {}
}

View File

@@ -1,11 +0,0 @@
// Generated automatically from javax.servlet.WriteListener for testing purposes
package javax.servlet;
import java.util.EventListener;
public interface WriteListener extends EventListener
{
void onError(Throwable p0);
void onWritePossible();
}

View File

@@ -1,18 +0,0 @@
// Generated automatically from javax.servlet.annotation.HttpConstraint for testing purposes
package javax.servlet.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.servlet.annotation.ServletSecurity;
@Documented
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
public @interface HttpConstraint
{
ServletSecurity.EmptyRoleSemantic value();
ServletSecurity.TransportGuarantee transportGuarantee();
String[] rolesAllowed();
}

View File

@@ -1,19 +0,0 @@
// Generated automatically from javax.servlet.annotation.HttpMethodConstraint for testing purposes
package javax.servlet.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.servlet.annotation.ServletSecurity;
@Documented
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
public @interface HttpMethodConstraint
{
ServletSecurity.EmptyRoleSemantic emptyRoleSemantic();
ServletSecurity.TransportGuarantee transportGuarantee();
String value();
String[] rolesAllowed();
}

View File

@@ -1,19 +0,0 @@
// Generated automatically from javax.servlet.annotation.MultipartConfig for testing purposes
package javax.servlet.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.TYPE})
public @interface MultipartConfig
{
String location();
int fileSizeThreshold();
long maxFileSize();
long maxRequestSize();
}

View File

@@ -1,33 +0,0 @@
// Generated automatically from javax.servlet.annotation.ServletSecurity for testing purposes
package javax.servlet.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.HttpMethodConstraint;
@Documented
@Inherited
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.TYPE})
public @interface ServletSecurity
{
HttpConstraint value();
HttpMethodConstraint[] httpMethodConstraints();
static public enum EmptyRoleSemantic
{
DENY, PERMIT;
private EmptyRoleSemantic() {}
}
static public enum TransportGuarantee
{
CONFIDENTIAL, NONE;
private TransportGuarantee() {}
}
}

View File

@@ -1,20 +0,0 @@
// Generated automatically from javax.servlet.annotation.WebInitParam for testing purposes
package javax.servlet.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.TYPE})
public @interface WebInitParam
{
String description();
String name();
String value();
}

View File

@@ -1,28 +0,0 @@
// Generated automatically from javax.servlet.annotation.WebServlet for testing purposes
package javax.servlet.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.servlet.annotation.WebInitParam;
@Documented
@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value={java.lang.annotation.ElementType.TYPE})
public @interface WebServlet
{
String description();
String displayName();
String largeIcon();
String name();
String smallIcon();
String[] urlPatterns();
String[] value();
WebInitParam[] initParams();
boolean asyncSupported();
int loadOnStartup();
}

View File

@@ -1,13 +0,0 @@
// Generated automatically from javax.servlet.descriptor.JspConfigDescriptor for testing purposes
package javax.servlet.descriptor;
import java.util.Collection;
import javax.servlet.descriptor.JspPropertyGroupDescriptor;
import javax.servlet.descriptor.TaglibDescriptor;
public interface JspConfigDescriptor
{
Collection<JspPropertyGroupDescriptor> getJspPropertyGroups();
Collection<TaglibDescriptor> getTaglibs();
}

View File

@@ -1,21 +0,0 @@
// Generated automatically from javax.servlet.descriptor.JspPropertyGroupDescriptor for testing purposes
package javax.servlet.descriptor;
import java.util.Collection;
public interface JspPropertyGroupDescriptor
{
Collection<String> getIncludeCodas();
Collection<String> getIncludePreludes();
Collection<String> getUrlPatterns();
String getBuffer();
String getDefaultContentType();
String getDeferredSyntaxAllowedAsLiteral();
String getElIgnored();
String getErrorOnUndeclaredNamespace();
String getIsXml();
String getPageEncoding();
String getScriptingInvalid();
String getTrimDirectiveWhitespaces();
}

View File

@@ -1,10 +0,0 @@
// Generated automatically from javax.servlet.descriptor.TaglibDescriptor for testing purposes
package javax.servlet.descriptor;
public interface TaglibDescriptor
{
String getTaglibLocation();
String getTaglibURI();
}

View File

@@ -1,29 +0,0 @@
// Generated automatically from javax.servlet.http.Cookie for testing purposes
package javax.servlet.http;
import java.io.Serializable;
public class Cookie implements Cloneable, Serializable
{
protected Cookie() {}
public Cookie(String p0, String p1){}
public Object clone(){ return null; }
public String getComment(){ return null; }
public String getDomain(){ return null; }
public String getName(){ return null; }
public String getPath(){ return null; }
public String getValue(){ return null; }
public boolean getSecure(){ return false; }
public boolean isHttpOnly(){ return false; }
public int getMaxAge(){ return 0; }
public int getVersion(){ return 0; }
public void setComment(String p0){}
public void setDomain(String p0){}
public void setHttpOnly(boolean p0){}
public void setMaxAge(int p0){}
public void setPath(String p0){}
public void setSecure(boolean p0){}
public void setValue(String p0){}
public void setVersion(int p0){}
}

View File

@@ -1,24 +0,0 @@
// Generated automatically from javax.servlet.http.HttpServlet for testing purposes
package javax.servlet.http;
import javax.servlet.GenericServlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
abstract public class HttpServlet extends GenericServlet
{
protected long getLastModified(HttpServletRequest p0){ return 0; }
protected void doDelete(HttpServletRequest p0, HttpServletResponse p1){}
protected void doGet(HttpServletRequest p0, HttpServletResponse p1){}
protected void doHead(HttpServletRequest p0, HttpServletResponse p1){}
protected void doOptions(HttpServletRequest p0, HttpServletResponse p1){}
protected void doPost(HttpServletRequest p0, HttpServletResponse p1){}
protected void doPut(HttpServletRequest p0, HttpServletResponse p1){}
protected void doTrace(HttpServletRequest p0, HttpServletResponse p1){}
protected void service(HttpServletRequest p0, HttpServletResponse p1){}
public HttpServlet(){}
public void service(ServletRequest p0, ServletResponse p1){}
}

View File

@@ -1,13 +0,0 @@
// Generated automatically from javax.servlet.http.HttpServletMapping for testing purposes
package javax.servlet.http;
import javax.servlet.http.MappingMatch;
public interface HttpServletMapping
{
MappingMatch getMappingMatch();
String getMatchValue();
String getPattern();
String getServletName();
}

View File

@@ -1,60 +0,0 @@
// Generated automatically from javax.servlet.http.HttpServletRequest for testing purposes
package javax.servlet.http;
import java.security.Principal;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletMapping;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpUpgradeHandler;
import javax.servlet.http.Part;
import javax.servlet.http.PushBuilder;
public interface HttpServletRequest extends ServletRequest
{
<T extends HttpUpgradeHandler> T upgrade(java.lang.Class<T> p0);
Collection<Part> getParts();
Cookie[] getCookies();
Enumeration<String> getHeaderNames();
Enumeration<String> getHeaders(String p0);
HttpSession getSession();
HttpSession getSession(boolean p0);
Part getPart(String p0);
Principal getUserPrincipal();
String changeSessionId();
String getAuthType();
String getContextPath();
String getHeader(String p0);
String getMethod();
String getPathInfo();
String getPathTranslated();
String getQueryString();
String getRemoteUser();
String getRequestURI();
String getRequestedSessionId();
String getServletPath();
StringBuffer getRequestURL();
boolean authenticate(HttpServletResponse p0);
boolean isRequestedSessionIdFromCookie();
boolean isRequestedSessionIdFromURL();
boolean isRequestedSessionIdFromUrl();
boolean isRequestedSessionIdValid();
boolean isUserInRole(String p0);
default HttpServletMapping getHttpServletMapping(){ return null; }
default Map<String, String> getTrailerFields(){ return null; }
default PushBuilder newPushBuilder(){ return null; }
default boolean isTrailerFieldsReady(){ return false; }
int getIntHeader(String p0);
long getDateHeader(String p0);
static String BASIC_AUTH = null;
static String CLIENT_CERT_AUTH = null;
static String DIGEST_AUTH = null;
static String FORM_AUTH = null;
void login(String p0, String p1);
void logout();
}

View File

@@ -1,77 +0,0 @@
// Generated automatically from javax.servlet.http.HttpServletResponse for testing purposes
package javax.servlet.http;
import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
public interface HttpServletResponse extends ServletResponse
{
Collection<String> getHeaderNames();
Collection<String> getHeaders(String p0);
String encodeRedirectURL(String p0);
String encodeRedirectUrl(String p0);
String encodeURL(String p0);
String encodeUrl(String p0);
String getHeader(String p0);
boolean containsHeader(String p0);
default Supplier<Map<String, String>> getTrailerFields(){ return null; }
default void setTrailerFields(Supplier<Map<String, String>> p0){}
int getStatus();
static int SC_ACCEPTED = 0;
static int SC_BAD_GATEWAY = 0;
static int SC_BAD_REQUEST = 0;
static int SC_CONFLICT = 0;
static int SC_CONTINUE = 0;
static int SC_CREATED = 0;
static int SC_EXPECTATION_FAILED = 0;
static int SC_FORBIDDEN = 0;
static int SC_FOUND = 0;
static int SC_GATEWAY_TIMEOUT = 0;
static int SC_GONE = 0;
static int SC_HTTP_VERSION_NOT_SUPPORTED = 0;
static int SC_INTERNAL_SERVER_ERROR = 0;
static int SC_LENGTH_REQUIRED = 0;
static int SC_METHOD_NOT_ALLOWED = 0;
static int SC_MOVED_PERMANENTLY = 0;
static int SC_MOVED_TEMPORARILY = 0;
static int SC_MULTIPLE_CHOICES = 0;
static int SC_NON_AUTHORITATIVE_INFORMATION = 0;
static int SC_NOT_ACCEPTABLE = 0;
static int SC_NOT_FOUND = 0;
static int SC_NOT_IMPLEMENTED = 0;
static int SC_NOT_MODIFIED = 0;
static int SC_NO_CONTENT = 0;
static int SC_OK = 0;
static int SC_PARTIAL_CONTENT = 0;
static int SC_PAYMENT_REQUIRED = 0;
static int SC_PRECONDITION_FAILED = 0;
static int SC_PROXY_AUTHENTICATION_REQUIRED = 0;
static int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 0;
static int SC_REQUEST_ENTITY_TOO_LARGE = 0;
static int SC_REQUEST_TIMEOUT = 0;
static int SC_REQUEST_URI_TOO_LONG = 0;
static int SC_RESET_CONTENT = 0;
static int SC_SEE_OTHER = 0;
static int SC_SERVICE_UNAVAILABLE = 0;
static int SC_SWITCHING_PROTOCOLS = 0;
static int SC_TEMPORARY_REDIRECT = 0;
static int SC_UNAUTHORIZED = 0;
static int SC_UNSUPPORTED_MEDIA_TYPE = 0;
static int SC_USE_PROXY = 0;
void addCookie(Cookie p0);
void addDateHeader(String p0, long p1);
void addHeader(String p0, String p1);
void addIntHeader(String p0, int p1);
void sendError(int p0);
void sendError(int p0, String p1);
void sendRedirect(String p0);
void setDateHeader(String p0, long p1);
void setHeader(String p0, String p1);
void setIntHeader(String p0, int p1);
void setStatus(int p0);
void setStatus(int p0, String p1);
}

View File

@@ -1,28 +0,0 @@
// Generated automatically from javax.servlet.http.HttpSession for testing purposes
package javax.servlet.http;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionContext;
public interface HttpSession
{
Enumeration<String> getAttributeNames();
HttpSessionContext getSessionContext();
Object getAttribute(String p0);
Object getValue(String p0);
ServletContext getServletContext();
String getId();
String[] getValueNames();
boolean isNew();
int getMaxInactiveInterval();
long getCreationTime();
long getLastAccessedTime();
void invalidate();
void putValue(String p0, Object p1);
void removeAttribute(String p0);
void removeValue(String p0);
void setAttribute(String p0, Object p1);
void setMaxInactiveInterval(int p0);
}

View File

@@ -1,12 +0,0 @@
// Generated automatically from javax.servlet.http.HttpSessionContext for testing purposes
package javax.servlet.http;
import java.util.Enumeration;
import javax.servlet.http.HttpSession;
public interface HttpSessionContext
{
Enumeration<String> getIds();
HttpSession getSession(String p0);
}

View File

@@ -1,11 +0,0 @@
// Generated automatically from javax.servlet.http.HttpUpgradeHandler for testing purposes
package javax.servlet.http;
import javax.servlet.http.WebConnection;
public interface HttpUpgradeHandler
{
void destroy();
void init(WebConnection p0);
}

View File

@@ -1,10 +0,0 @@
// Generated automatically from javax.servlet.http.MappingMatch for testing purposes
package javax.servlet.http;
public enum MappingMatch
{
CONTEXT_ROOT, DEFAULT, EXACT, EXTENSION, PATH;
private MappingMatch() {}
}

View File

@@ -1,20 +0,0 @@
// Generated automatically from javax.servlet.http.Part for testing purposes
package javax.servlet.http;
import java.io.InputStream;
import java.util.Collection;
public interface Part
{
Collection<String> getHeaderNames();
Collection<String> getHeaders(String p0);
InputStream getInputStream();
String getContentType();
String getHeader(String p0);
String getName();
String getSubmittedFileName();
long getSize();
void delete();
void write(String p0);
}

View File

@@ -1,23 +0,0 @@
// Generated automatically from javax.servlet.http.PushBuilder for testing purposes
package javax.servlet.http;
import java.util.Set;
public interface PushBuilder
{
PushBuilder addHeader(String p0, String p1);
PushBuilder method(String p0);
PushBuilder path(String p0);
PushBuilder queryString(String p0);
PushBuilder removeHeader(String p0);
PushBuilder sessionId(String p0);
PushBuilder setHeader(String p0, String p1);
Set<String> getHeaderNames();
String getHeader(String p0);
String getMethod();
String getPath();
String getQueryString();
String getSessionId();
void push();
}

View File

@@ -1,12 +0,0 @@
// Generated automatically from javax.servlet.http.WebConnection for testing purposes
package javax.servlet.http;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
public interface WebConnection extends AutoCloseable
{
ServletInputStream getInputStream();
ServletOutputStream getOutputStream();
}