Search in sources :

Example 66 with JwtClaims

use of org.jose4j.jwt.JwtClaims in project stdlib by petergeneric.

the class JwtCreationRestServiceImpl method getResult.

@Override
public String getResult(String token, final String secret, final String payload, final String op) {
    final TemplateCall template = templater.template(PREFIX + "jwt_generated.html");
    final Long expireTime;
    if (token == null) {
        try {
            JwtClaims claims = JwtClaims.parse(payload);
            if (claims.getExpirationTime() != null)
                expireTime = claims.getExpirationTime().getValueInMillis();
            else
                expireTime = null;
            token = createJWT(secret, payload);
        } catch (InvalidJwtException | MalformedClaimException | JoseException e) {
            throw new RuntimeException(e);
        }
    } else {
        // User has provided a JWT. We should simply parse it and extract the expiry time (for the cookie)
        try {
            JwtConsumer jwtConsumer = new JwtConsumerBuilder().setSkipAllValidators().setDisableRequireSignature().setSkipSignatureVerification().build();
            final JwtClaims claims = jwtConsumer.processToClaims(token);
            if (claims.getExpirationTime() != null)
                expireTime = claims.getExpirationTime().getValueInMillis();
            else
                expireTime = null;
        } catch (InvalidJwtException | MalformedClaimException e) {
            throw new RuntimeException(e);
        }
    }
    final boolean save = StringUtils.equalsIgnoreCase("save", op);
    // Optionally save as a cookie
    if (save) {
        Cookie cookie = new Cookie(cookieName, token);
        // Set the cookie path based on the webapp endpoint path
        cookie.setPath(webappEndpoint.getPath());
        // If the webapp has an https endpoint (or if we were accessed by HTTPS) then set the cookie as a secure cookie
        cookie.setSecure(HttpCallContext.get().getRequest().isSecure() || StringUtils.equalsIgnoreCase("https", webappEndpoint.getScheme()));
        // Expire the cookie 1 minute before the token expires
        if (expireTime != null)
            cookie.setMaxAge(expireTime.intValue() - 60);
        // Kill the current session (just in case it's associated with a job manager login)
        final HttpSession session = HttpCallContext.get().getRequest().getSession(false);
        if (session != null) {
            session.invalidate();
        }
        // Now add the JWT cookie
        HttpCallContext.get().getResponse().addCookie(cookie);
    }
    template.set("saved", save);
    template.set("token", token);
    return template.process();
}
Also used : InvalidJwtException(org.jose4j.jwt.consumer.InvalidJwtException) Cookie(javax.servlet.http.Cookie) JwtClaims(org.jose4j.jwt.JwtClaims) JoseException(org.jose4j.lang.JoseException) JwtConsumerBuilder(org.jose4j.jwt.consumer.JwtConsumerBuilder) HttpSession(javax.servlet.http.HttpSession) TemplateCall(com.peterphi.std.guice.web.rest.templating.TemplateCall) MalformedClaimException(org.jose4j.jwt.MalformedClaimException) JwtConsumer(org.jose4j.jwt.consumer.JwtConsumer)

Example 67 with JwtClaims

use of org.jose4j.jwt.JwtClaims in project blockchain-java-api-client by astarlabs.

the class Token method sign.

public static String sign(String key) throws Exception {
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    String decoded = new String(Hex.decode(key));
    String replaced = decoded.replaceAll("-----BEGIN RSA PRIVATE KEY-----", "").replaceAll("-----END RSA PRIVATE KEY-----", "").replaceAll("\\s", "");
    byte[] encodedPrivateKey = Base64.getDecoder().decode(replaced);
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
    KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
    PrivateKey privKey = kf.generatePrivate(keySpec);
    JwtClaims claims = new JwtClaims();
    claims.setExpirationTimeMinutesInTheFuture(10);
    claims.setGeneratedJwtId();
    claims.setIssuedAtToNow();
    claims.setNotBeforeMinutesInThePast(2);
    JsonWebSignature jws = new JsonWebSignature();
    jws.setPayload(claims.toJson());
    jws.setKey(privKey);
    jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
    String innerJwt = jws.getCompactSerialization();
    return innerJwt;
}
Also used : PrivateKey(java.security.PrivateKey) JsonWebSignature(org.jose4j.jws.JsonWebSignature) JwtClaims(org.jose4j.jwt.JwtClaims) PKCS8EncodedKeySpec(java.security.spec.PKCS8EncodedKeySpec) KeyFactory(java.security.KeyFactory)

Example 68 with JwtClaims

use of org.jose4j.jwt.JwtClaims in project light-rest-4j by networknt.

the class JwtVerifyHandler method handleRequest.

@Override
public void handleRequest(final HttpServerExchange exchange) throws Exception {
    HeaderMap headerMap = exchange.getRequestHeaders();
    String authorization = headerMap.getFirst(Headers.AUTHORIZATION);
    String jwt = JwtHelper.getJwtFromAuthorization(authorization);
    if (jwt != null) {
        try {
            JwtClaims claims = JwtHelper.verifyJwt(jwt);
            Map<String, Object> auditInfo = exchange.getAttachment(AuditHandler.AUDIT_INFO);
            // endpoint and swaggerOperation available. This handler will enrich the auditInfo.
            if (auditInfo == null) {
                auditInfo = new HashMap<>();
                exchange.putAttachment(AuditHandler.AUDIT_INFO, auditInfo);
            }
            auditInfo.put(Constants.CLIENT_ID_STRING, claims.getStringClaimValue(Constants.CLIENT_ID_STRING));
            auditInfo.put(Constants.USER_ID_STRING, claims.getStringClaimValue(Constants.USER_ID_STRING));
            auditInfo.put(Constants.SUBJECT_CLAIMS, claims);
            if (config != null && (Boolean) config.get(ENABLE_VERIFY_SCOPE) && SwaggerHelper.swagger != null) {
                Operation operation = null;
                SwaggerOperation swaggerOperation = (SwaggerOperation) auditInfo.get(Constants.SWAGGER_OPERATION_STRING);
                if (swaggerOperation == null) {
                    final NormalisedPath requestPath = new ApiNormalisedPath(exchange.getRequestURI());
                    final Optional<NormalisedPath> maybeApiPath = SwaggerHelper.findMatchingApiPath(requestPath);
                    if (!maybeApiPath.isPresent()) {
                        Status status = new Status(STATUS_INVALID_REQUEST_PATH);
                        exchange.setStatusCode(status.getStatusCode());
                        logger.error("Error in JwtVerifyHandler: " + status.toString());
                        exchange.getResponseSender().send(status.toString());
                        return;
                    }
                    final NormalisedPath swaggerPathString = maybeApiPath.get();
                    final Path swaggerPath = SwaggerHelper.swagger.getPath(swaggerPathString.original());
                    final HttpMethod httpMethod = HttpMethod.valueOf(exchange.getRequestMethod().toString());
                    operation = swaggerPath.getOperationMap().get(httpMethod);
                    if (operation == null) {
                        Status status = new Status(STATUS_METHOD_NOT_ALLOWED);
                        exchange.setStatusCode(status.getStatusCode());
                        logger.error("Error in JwtVerifyHandler: " + status.toString());
                        exchange.getResponseSender().send(status.toString());
                        return;
                    }
                    swaggerOperation = new SwaggerOperation(swaggerPathString, swaggerPath, httpMethod, operation);
                    auditInfo.put(Constants.SWAGGER_OPERATION_STRING, swaggerOperation);
                    auditInfo.put(Constants.ENDPOINT_STRING, swaggerPathString.normalised() + "@" + httpMethod);
                } else {
                    operation = swaggerOperation.getOperation();
                }
                // is there a scope token
                String scopeHeader = headerMap.getFirst(Constants.SCOPE_TOKEN);
                String scopeJwt = JwtHelper.getJwtFromAuthorization(scopeHeader);
                List<String> secondaryScopes = null;
                if (scopeJwt != null) {
                    try {
                        JwtClaims scopeClaims = JwtHelper.verifyJwt(scopeJwt);
                        secondaryScopes = scopeClaims.getStringListClaimValue("scope");
                        auditInfo.put(Constants.SCOPE_CLIENT_ID_STRING, scopeClaims.getStringClaimValue(Constants.CLIENT_ID_STRING));
                        auditInfo.put(Constants.ACCESS_CLAIMS, scopeClaims);
                    } catch (InvalidJwtException | MalformedClaimException e) {
                        logger.error("InvalidJwtException", e);
                        Status status = new Status(STATUS_INVALID_SCOPE_TOKEN);
                        exchange.setStatusCode(status.getStatusCode());
                        logger.error("Error in JwtVerifyHandler: " + status.toString());
                        exchange.getResponseSender().send(status.toString());
                        return;
                    } catch (ExpiredTokenException e) {
                        Status status = new Status(STATUS_SCOPE_TOKEN_EXPIRED);
                        exchange.setStatusCode(status.getStatusCode());
                        logger.error("Error in JwtVerifyHandler: " + status.toString());
                        exchange.getResponseSender().send(status.toString());
                        return;
                    }
                }
                // get scope defined in swagger spec for this endpoint.
                List<String> specScopes = null;
                List<Map<String, List<String>>> security = operation.getSecurity();
                if (security != null) {
                    for (Map<String, List<String>> requirement : security) {
                        specScopes = requirement.get(SwaggerHelper.oauth2Name);
                        if (specScopes != null)
                            break;
                    }
                }
                // validate scope
                if (scopeHeader != null) {
                    if (secondaryScopes == null || !matchedScopes(secondaryScopes, specScopes)) {
                        Status status = new Status(STATUS_SCOPE_TOKEN_SCOPE_MISMATCH, secondaryScopes, specScopes);
                        exchange.setStatusCode(status.getStatusCode());
                        logger.error("Error in JwtVerifyHandler: " + status.toString());
                        exchange.getResponseSender().send(status.toString());
                        return;
                    }
                } else {
                    // no scope token, verify scope from auth token.
                    List<String> primaryScopes;
                    try {
                        primaryScopes = claims.getStringListClaimValue("scope");
                    } catch (MalformedClaimException e) {
                        logger.error("MalformedClaimException", e);
                        Status status = new Status(STATUS_INVALID_AUTH_TOKEN);
                        exchange.setStatusCode(status.getStatusCode());
                        logger.error("Error in JwtVerifyHandler: " + status.toString());
                        exchange.getResponseSender().send(status.toString());
                        return;
                    }
                    if (!matchedScopes(primaryScopes, specScopes)) {
                        Status status = new Status(STATUS_AUTH_TOKEN_SCOPE_MISMATCH, primaryScopes, specScopes);
                        exchange.setStatusCode(status.getStatusCode());
                        logger.error("Error in JwtVerifyHandler: " + status.toString());
                        exchange.getResponseSender().send(status.toString());
                        return;
                    }
                }
            }
            next.handleRequest(exchange);
        } catch (InvalidJwtException e) {
            // only log it and unauthorized is returned.
            logger.error("Exception: ", e);
            Status status = new Status(STATUS_INVALID_AUTH_TOKEN);
            exchange.setStatusCode(status.getStatusCode());
            logger.error("Error in JwtVerifyHandler: " + status.toString());
            exchange.getResponseSender().send(status.toString());
        } catch (ExpiredTokenException e) {
            Status status = new Status(STATUS_AUTH_TOKEN_EXPIRED);
            exchange.setStatusCode(status.getStatusCode());
            logger.error("Error in JwtVerifyHandler: " + status.toString());
            exchange.getResponseSender().send(status.toString());
        }
    } else {
        Status status = new Status(STATUS_MISSING_AUTH_TOKEN);
        exchange.setStatusCode(status.getStatusCode());
        logger.error("Error in JwtVerifyHandler: " + status.toString());
        exchange.getResponseSender().send(status.toString());
    }
}
Also used : Status(com.networknt.status.Status) InvalidJwtException(org.jose4j.jwt.consumer.InvalidJwtException) ExpiredTokenException(com.networknt.exception.ExpiredTokenException) JwtClaims(org.jose4j.jwt.JwtClaims) HttpString(io.undertow.util.HttpString) MalformedClaimException(org.jose4j.jwt.MalformedClaimException) HeaderMap(io.undertow.util.HeaderMap) List(java.util.List) HashMap(java.util.HashMap) HeaderMap(io.undertow.util.HeaderMap) Map(java.util.Map)

Example 69 with JwtClaims

use of org.jose4j.jwt.JwtClaims in project cas by apereo.

the class OidcIdTokenGeneratorService method buildJwtClaims.

/**
 * Produce claims as jwt.
 * As per OpenID Connect Core section 5.4, 'The Claims requested by the profile,
 * email, address, and phone scope values are returned from the UserInfo Endpoint',
 * except for response_type=id_token, where they are returned in the id_token
 * (as there is no access token issued that could be used to access the userinfo endpoint).
 *
 * @param accessToken      the access token
 * @param timeoutInSeconds the timeoutInSeconds
 * @param service          the service
 * @param responseType     the response type
 * @param grantType        the grant type
 * @return the jwt claims
 */
protected JwtClaims buildJwtClaims(final OAuth20AccessToken accessToken, final long timeoutInSeconds, final OidcRegisteredService service, final OAuth20ResponseTypes responseType, final OAuth20GrantTypes grantType) {
    val authentication = accessToken.getAuthentication();
    val principal = getConfigurationContext().getProfileScopeToAttributesFilter().filter(accessToken.getService(), authentication.getPrincipal(), service, accessToken);
    LOGGER.debug("Principal to use to build th ID token is [{}]", principal);
    val oidc = getConfigurationContext().getCasProperties().getAuthn().getOidc();
    val claims = new JwtClaims();
    val tgt = accessToken.getTicketGrantingTicket();
    val jwtId = getJwtId(tgt);
    claims.setJwtId(jwtId);
    claims.setClaim(OidcConstants.CLAIM_SESSION_ID, DigestUtils.sha(jwtId));
    claims.setIssuer(getConfigurationContext().getIssuerService().determineIssuer(Optional.empty()));
    claims.setAudience(accessToken.getClientId());
    val expirationDate = NumericDate.now();
    expirationDate.addSeconds(timeoutInSeconds);
    claims.setExpirationTime(expirationDate);
    claims.setIssuedAtToNow();
    claims.setNotBeforeMinutesInThePast((float) Beans.newDuration(oidc.getCore().getSkew()).toMinutes());
    claims.setSubject(principal.getId());
    val mfa = getConfigurationContext().getCasProperties().getAuthn().getMfa();
    val attributes = authentication.getAttributes();
    if (attributes.containsKey(mfa.getCore().getAuthenticationContextAttribute())) {
        val acrValues = CollectionUtils.toCollection(attributes.get(mfa.getCore().getAuthenticationContextAttribute()));
        val authnContexts = oidc.getCore().getAuthenticationContextReferenceMappings();
        val mappings = CollectionUtils.convertDirectedListToMap(authnContexts);
        val acrMapped = acrValues.stream().map(acrValue -> mappings.entrySet().stream().filter(entry -> entry.getValue().equalsIgnoreCase(acrValue.toString())).map(Map.Entry::getKey).findFirst().orElseGet(acrValue::toString)).collect(Collectors.joining(" "));
        LOGGER.debug("ID token acr claim calculated as [{}]", acrMapped);
        claims.setStringClaim(OidcConstants.ACR, acrMapped);
    }
    if (attributes.containsKey(AuthenticationHandler.SUCCESSFUL_AUTHENTICATION_HANDLERS)) {
        val val = CollectionUtils.toCollection(attributes.get(AuthenticationHandler.SUCCESSFUL_AUTHENTICATION_HANDLERS));
        claims.setStringListClaim(OidcConstants.AMR, val.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
    }
    claims.setStringClaim(OAuth20Constants.CLIENT_ID, service.getClientId());
    claims.setClaim(OidcConstants.CLAIM_AUTH_TIME, tgt.getAuthentication().getAuthenticationDate().toEpochSecond());
    if (attributes.containsKey(OAuth20Constants.STATE)) {
        setClaim(claims, OAuth20Constants.STATE, attributes.get(OAuth20Constants.STATE).get(0));
    }
    if (attributes.containsKey(OAuth20Constants.NONCE)) {
        setClaim(claims, OAuth20Constants.NONCE, attributes.get(OAuth20Constants.NONCE).get(0));
    }
    generateAccessTokenHash(accessToken, service, claims);
    val includeClaims = responseType != OAuth20ResponseTypes.CODE && grantType != OAuth20GrantTypes.AUTHORIZATION_CODE;
    if (includeClaims || oidc.getCore().isIncludeIdTokenClaims()) {
        FunctionUtils.doIf(oidc.getCore().isIncludeIdTokenClaims(), ignore -> LOGGER.warn("Individual claims requested by OpenID scopes are forced to be included in the ID token. " + "This is a violation of the OpenID Connect specification and a workaround via dedicated CAS configuration. " + "Claims should be requested from the userinfo/profile endpoints in exchange for an access token.")).accept(claims);
        collectIdTokenClaims(principal, claims);
    } else {
        LOGGER.debug("Per OpenID Connect specification, individual claims requested by OpenID scopes " + "such as profile, email, address, etc. are only put " + "into the OpenID Connect ID token when the response type is set to id_token.");
    }
    return claims;
}
Also used : lombok.val(lombok.val) OAuth20AccessTokenAtHashGenerator(org.apereo.cas.support.oauth.web.response.accesstoken.OAuth20AccessTokenAtHashGenerator) DigestUtils(org.apereo.cas.util.DigestUtils) ArrayUtils(org.apache.commons.lang3.ArrayUtils) BooleanUtils(org.apache.commons.lang3.BooleanUtils) Beans(org.apereo.cas.configuration.support.Beans) StringUtils(org.apache.commons.lang3.StringUtils) ArrayList(java.util.ArrayList) FunctionUtils(org.apereo.cas.util.function.FunctionUtils) ObjectProvider(org.springframework.beans.factory.ObjectProvider) AuthenticationHandler(org.apereo.cas.authentication.AuthenticationHandler) Map(java.util.Map) CollectionUtils(org.apereo.cas.util.CollectionUtils) TicketGrantingTicket(org.apereo.cas.ticket.TicketGrantingTicket) OAuth20JwtAccessTokenEncoder(org.apereo.cas.support.oauth.web.response.accesstoken.response.OAuth20JwtAccessTokenEncoder) OAuth20Constants(org.apereo.cas.support.oauth.OAuth20Constants) OAuth20ResponseTypes(org.apereo.cas.support.oauth.OAuth20ResponseTypes) BaseIdTokenGeneratorService(org.apereo.cas.ticket.BaseIdTokenGeneratorService) OAuth20GrantTypes(org.apereo.cas.support.oauth.OAuth20GrantTypes) OidcConstants(org.apereo.cas.oidc.OidcConstants) lombok.val(lombok.val) OAuthRegisteredService(org.apereo.cas.support.oauth.services.OAuthRegisteredService) Collectors(java.util.stream.Collectors) OAuth20AccessToken(org.apereo.cas.ticket.accesstoken.OAuth20AccessToken) OidcConfigurationContext(org.apereo.cas.oidc.OidcConfigurationContext) Objects(java.util.Objects) Slf4j(lombok.extern.slf4j.Slf4j) NumericDate(org.jose4j.jwt.NumericDate) OidcRegisteredService(org.apereo.cas.services.OidcRegisteredService) Stream(java.util.stream.Stream) JwtClaims(org.jose4j.jwt.JwtClaims) Optional(java.util.Optional) Principal(org.apereo.cas.authentication.principal.Principal) UserProfile(org.pac4j.core.profile.UserProfile) Assert(org.springframework.util.Assert) JwtClaims(org.jose4j.jwt.JwtClaims)

Example 70 with JwtClaims

use of org.jose4j.jwt.JwtClaims in project cas by apereo.

the class OidcIdTokenGeneratorService method collectIdTokenClaims.

/**
 * Collect id token claims.
 *
 * @param principal the principal
 * @param claims    the claims
 */
protected void collectIdTokenClaims(final Principal principal, final JwtClaims claims) {
    val oidc = getConfigurationContext().getCasProperties().getAuthn().getOidc();
    LOGGER.trace("Comparing principal attributes [{}] with supported claims [{}]", principal.getAttributes(), oidc.getDiscovery().getClaims());
    principal.getAttributes().entrySet().stream().filter(entry -> {
        if (oidc.getDiscovery().getClaims().contains(entry.getKey())) {
            LOGGER.trace("Found supported claim [{}]", entry.getKey());
            return true;
        }
        LOGGER.warn("Claim [{}] is not defined as a supported claim among [{}]. Skipping...", entry.getKey(), oidc.getDiscovery().getClaims());
        return false;
    }).forEach(entry -> handleMappedClaimOrDefault(entry.getKey(), principal, claims, entry.getValue()));
    if (!claims.hasClaim(OidcConstants.CLAIM_PREFERRED_USERNAME)) {
        handleMappedClaimOrDefault(OidcConstants.CLAIM_PREFERRED_USERNAME, principal, claims, principal.getId());
    }
}
Also used : lombok.val(lombok.val) OAuth20AccessTokenAtHashGenerator(org.apereo.cas.support.oauth.web.response.accesstoken.OAuth20AccessTokenAtHashGenerator) DigestUtils(org.apereo.cas.util.DigestUtils) ArrayUtils(org.apache.commons.lang3.ArrayUtils) BooleanUtils(org.apache.commons.lang3.BooleanUtils) Beans(org.apereo.cas.configuration.support.Beans) StringUtils(org.apache.commons.lang3.StringUtils) ArrayList(java.util.ArrayList) FunctionUtils(org.apereo.cas.util.function.FunctionUtils) ObjectProvider(org.springframework.beans.factory.ObjectProvider) AuthenticationHandler(org.apereo.cas.authentication.AuthenticationHandler) Map(java.util.Map) CollectionUtils(org.apereo.cas.util.CollectionUtils) TicketGrantingTicket(org.apereo.cas.ticket.TicketGrantingTicket) OAuth20JwtAccessTokenEncoder(org.apereo.cas.support.oauth.web.response.accesstoken.response.OAuth20JwtAccessTokenEncoder) OAuth20Constants(org.apereo.cas.support.oauth.OAuth20Constants) OAuth20ResponseTypes(org.apereo.cas.support.oauth.OAuth20ResponseTypes) BaseIdTokenGeneratorService(org.apereo.cas.ticket.BaseIdTokenGeneratorService) OAuth20GrantTypes(org.apereo.cas.support.oauth.OAuth20GrantTypes) OidcConstants(org.apereo.cas.oidc.OidcConstants) lombok.val(lombok.val) OAuthRegisteredService(org.apereo.cas.support.oauth.services.OAuthRegisteredService) Collectors(java.util.stream.Collectors) OAuth20AccessToken(org.apereo.cas.ticket.accesstoken.OAuth20AccessToken) OidcConfigurationContext(org.apereo.cas.oidc.OidcConfigurationContext) Objects(java.util.Objects) Slf4j(lombok.extern.slf4j.Slf4j) NumericDate(org.jose4j.jwt.NumericDate) OidcRegisteredService(org.apereo.cas.services.OidcRegisteredService) Stream(java.util.stream.Stream) JwtClaims(org.jose4j.jwt.JwtClaims) Optional(java.util.Optional) Principal(org.apereo.cas.authentication.principal.Principal) UserProfile(org.pac4j.core.profile.UserProfile) Assert(org.springframework.util.Assert)

Aggregations

JwtClaims (org.jose4j.jwt.JwtClaims)120 Test (org.junit.Test)47 MalformedClaimException (org.jose4j.jwt.MalformedClaimException)18 JwtConsumer (org.jose4j.jwt.consumer.JwtConsumer)18 JwtConsumerBuilder (org.jose4j.jwt.consumer.JwtConsumerBuilder)17 InvalidJwtException (org.jose4j.jwt.consumer.InvalidJwtException)16 lombok.val (lombok.val)15 JoseException (org.jose4j.lang.JoseException)15 JsonWebSignature (org.jose4j.jws.JsonWebSignature)13 Map (java.util.Map)12 JwtContext (org.jose4j.jwt.consumer.JwtContext)11 JsonWebStructure (org.jose4j.jwx.JsonWebStructure)9 NumericDate (org.jose4j.jwt.NumericDate)8 KeyStoreException (java.security.KeyStoreException)6 ExpiredTokenException (com.networknt.exception.ExpiredTokenException)5 ArrayList (java.util.ArrayList)5 HashMap (java.util.HashMap)5 OidcRegisteredService (org.apereo.cas.services.OidcRegisteredService)5 JwksVerificationKeyResolver (org.jose4j.keys.resolvers.JwksVerificationKeyResolver)4 Test (org.junit.jupiter.api.Test)4