de6d4644创建于 2024年11月4日历史提交
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2024. All rights reserved.
 */
package jwt4cj

/*
 * Used to verify the JWT for its signature and claims.
 * Implementations must be thread-safe.
 * Instances are created using Verification.
 */
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
     */
    func verify(token: String): DecodedJWT

    /*
     * Performs the verification against the given DecodedJWT.
     *
     * @param jwt to verify.
     * @return a verified and decoded JWT.
     * @throws JWTVerificationException if any of the verification steps fail
     */
    func verify(jwt: DecodedJWT): DecodedJWT
}

public class BaseJWTVerifier <: JWTVerifier {
    private let algorithm: Algorithm

    private let expectedChecks: ArrayList<ExpectedCheckHolder>

    private let parser: JWTParser

    init(algorithm: Algorithm, expectedChecks: ArrayList<ExpectedCheckHolder>) {
        this.algorithm = algorithm
        this.expectedChecks = expectedChecks
        this.parser = JWTParser()
    }

    static func builder(algorithm: Algorithm): Verification {
        try {
            return BaseVerification(algorithm)
        } catch (e: IllegalArgumentException) {
            throw IllegalArgumentException("Illegal Argument " + algorithm.toString())
        }
    }

    public func verify(token: String): DecodedJWT {
        var jwt: DecodedJWT = 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.
     */
    public func verify(jwt: DecodedJWT): DecodedJWT {
        verifyAlgorithm(jwt, algorithm)
        algorithm.verify(jwt)
        verifyClaims(jwt, expectedChecks)
        return jwt
    }

    private func verifyAlgorithm(jwt: DecodedJWT, expectedAlgorithm: Algorithm) {
        // let a = jwt.getAlgorithm()                           
        // match(a){
        //     case Some(v) => if(v!=expectedAlgorithm.getName()){throw Exception()}
        //     case None => throw AlgorithmMismatchException(
        //         "The provided Algorithm doesn't match the one defined in the JWT's Header.")
        // }
        if (expectedAlgorithm.getName() != jwt.getAlgorithm()) {
            throw AlgorithmMismatchException(
                "The provided Algorithm doesn't match the one defined in the JWT's Header.")
        }
    }

    private func verifyClaims(jwt: DecodedJWT, expectedChecks: ArrayList<ExpectedCheckHolder>) {
        for (expectedCheck in expectedChecks) {
            var isValid: Bool
            var claimName: String = expectedCheck.getClaimName()
            var claim: Claim = jwt.getClaim(claimName)

            // if (claim.isMissing() && claimName != "exp" && claimName != "nbf" && claimName != "iat") {
            //     println("missing")
            //     throw MissingClaimException(claimName)
            // }
            isValid = expectedCheck.verify(claim, jwt)

            if (!isValid) {
                throw IncorrectClaimException(
                    "The Claim '${claimName}' value doesn't match the required one.",
                    claimName,
                    claim
                )
            }
        }
    }
}