
com.mercateo.spring.security.jwt.token.verifier.JWTVerifier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spring-security-jwt Show documentation
Show all versions of spring-security-jwt Show documentation
JWT authentication with spring security
The newest version!
/*
* Copyright © 2017 Mercateo AG (http://www.mercateo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mercateo.spring.security.jwt.token.verifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.InvalidClaimException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.impl.PublicClaims;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.Clock;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.RSAKeyProvider;
import com.google.common.annotations.VisibleForTesting;
import lombok.val;
/**
* The JWTVerifier class holds the verify method to assert that a given Token
* has not only a proper JWT format, but also it's signature matches.
*/
@SuppressWarnings("WeakerAccess")
public final class JWTVerifier {
private final Map claims;
private final RSAKeyProvider rsaKeyProvider;
private final Clock clock;
JWTVerifier(RSAKeyProvider rsaKeyProvider, Map claims, Clock clock) {
this.rsaKeyProvider = rsaKeyProvider;
this.claims = Collections.unmodifiableMap(claims);
this.clock = clock;
}
/**
* Initialize a JWTVerifier instance using the given Algorithm.
*
* @param RSA key provider for the RSA algorithm.
* @return a JWTVerifier.Verification instance to configure.
* @throws IllegalArgumentException if the provided algorithm is null.
*/
public static BaseVerification init(RSAKeyProvider rsaKeyProvider) throws IllegalArgumentException {
return new BaseVerification(rsaKeyProvider);
}
/**
* 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 it's 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 InvalidClaimException
* if a claim contained a different value than the expected one.
*/
public DecodedJWT verify(String token) throws JWTVerificationException {
DecodedJWT jwt = JWT.decode(token);
Algorithm algorithm = getAlgorithm(jwt);
algorithm.verify(jwt);
verifyClaims(jwt, claims);
return jwt;
}
@VisibleForTesting
Algorithm getAlgorithm(DecodedJWT jwt) throws AlgorithmMismatchException {
switch (jwt.getAlgorithm().toLowerCase()) {
case "rs256":
return Algorithm.RSA256(rsaKeyProvider);
case "rs384":
return Algorithm.RSA384(rsaKeyProvider);
case "rs512":
return Algorithm.RSA512(rsaKeyProvider);
default:
throw new AlgorithmMismatchException(
"The provided Algorithm has to be RSA.");
}
}
private void verifyClaims(DecodedJWT jwt, Map claims) throws TokenExpiredException,
InvalidClaimException {
for (Map.Entry entry : claims.entrySet()) {
switch (entry.getKey()) {
case PublicClaims.AUDIENCE:
// noinspection unchecked
assertValidAudienceClaim(jwt.getAudience(), (Set) entry.getValue());
break;
case PublicClaims.EXPIRES_AT:
assertValidDateClaim(jwt.getExpiresAt(), (Long) entry.getValue(), true);
break;
case PublicClaims.NOT_BEFORE:
assertValidDateClaim(jwt.getNotBefore(), (Long) entry.getValue(), false);
break;
default:
assertValidClaim(jwt.getClaim(entry.getKey()), entry.getKey(), entry.getValue());
break;
}
}
}
private void assertValidClaim(Claim claim, String claimName, Object value) {
boolean isValid = false;
if (value instanceof String) {
isValid = value.equals(claim.asString());
} else if (value instanceof Integer) {
isValid = value.equals(claim.asInt());
} else if (value instanceof Long) {
isValid = value.equals(claim.asLong());
} else if (value instanceof Boolean) {
isValid = value.equals(claim.asBoolean());
} else if (value instanceof Double) {
isValid = value.equals(claim.asDouble());
} else if (value instanceof Date) {
isValid = value.equals(claim.asDate());
} else if (value instanceof Object[]) {
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy