@ShellMethod(key = "generate-full-jwt", value = "Generate JWT and sign it using a given keystore")
    public String generateKey(
        @ShellOption(value = {"jwks", "--jwks"}, defaultValue = StringUtils.EMPTY, help = "Path to the JWKS file used to sign the token")
        final String jwks,
        @ShellOption(value = {"iss", "--iss"}, defaultValue = "https://localhost:8443/cas/oidc", help = "Issuer")
        final String iss,
        @ShellOption(value = {"claims", "--claims"}, defaultValue = "{}", help = "JWT claims as JSON")
        final String claims,
        @ShellOption(value = {"aud", "--aud"}, defaultValue = "CAS", help = "Audience")
        final String aud,
        @ShellOption(value = {"exp", "--exp"}, defaultValue = "300", help = "Expiration in seconds")
        final String exp,
        @ShellOption(value = {"sub", "--sub"}, help = "Subject")
        final String sub) throws Exception {

        val jwtClaims = new JwtClaims();
        jwtClaims.setJwtId(RandomUtils.randomAlphanumeric(8));
        jwtClaims.setIssuer(iss);
        jwtClaims.setAudience(aud);

        if (NumberUtils.isParsable(exp)) {
            val expireInSeconds = Long.parseLong(exp);
            if (expireInSeconds > 0) {
                val expirationDate = NumericDate.now();
                expirationDate.addSeconds(expireInSeconds);
                jwtClaims.setExpirationTime(expirationDate);
            }
        } else {
            val expirationDate = NumericDate.fromMilliseconds(Beans.newDuration(exp).toSeconds());
            jwtClaims.setExpirationTime(expirationDate);
        }
        jwtClaims.setIssuedAtToNow();
        jwtClaims.setNotBeforeMinutesInThePast(1);
        jwtClaims.setSubject(sub);

        val otherClaims = MAPPER.readValue(JsonValue.readHjson(claims).toString(), Map.class);
        otherClaims.forEach((key, value) -> jwtClaims.setClaim(key.toString(), value));

        if (StringUtils.isNotBlank(jwks)) {
            val keystore = new JsonWebKeySet(FileUtils.readFileToString(new File(jwks), StandardCharsets.UTF_8));
            val jsonWebKey = (PublicJsonWebKey) keystore.getJsonWebKeys()
                .stream()
                .filter(key -> StringUtils.equalsIgnoreCase(key.getUse(), "signing"))
                .findFirst()
                .orElseGet(() -> keystore.getJsonWebKeys().getFirst());
            val jwt = EncodingUtils.signJwsRSASha512(jsonWebKey.getPrivateKey(),
                jwtClaims.toJson().getBytes(StandardCharsets.UTF_8), Map.of());
            val token = new String(jwt, StandardCharsets.UTF_8);
            //CHECKSTYLE:OFF
            LOGGER.info("Producing signed JWT:\n{}\n", token);
            //CHECKSTYLE:ON
            return token;
        }
        val jwt = new PlainJWT(JWTClaimsSet.parse(jwtClaims.getClaimsMap()));
        val token = jwt.serialize();
        //CHECKSTYLE:OFF
        LOGGER.info("Producing plain JWT:\n{}\n", token);
        //CHECKSTYLE:ON
        return token;
    }
Generate key string.

@param jwks   the jwks
@param iss    the iss
@param claims the claims
@param aud    the aud
@param exp    the exp
@param sub    the sub
@return the string
@throws Exception the exception
support/cas-server-support-shell-core/src/main/java/org/apereo/cas/shell/commands/jwt/GenerateFullJwtCommand.java