private String generateKid(JsonValue jwkSet, String algorithm) {

    final JwsAlgorithm jwsAlgorithm = JwsAlgorithm.valueOf(algorithm);
    if (JwsAlgorithmType.RSA.equals(jwsAlgorithm.getAlgorithmType())) {
      JsonValue jwks = jwkSet.get(OAuth2Constants.JWTTokenParams.KEYS);
      if (!jwks.isNull() && !jwks.asList().isEmpty()) {
        return jwks.get(0).get(OAuth2Constants.JWTTokenParams.KEY_ID).asString();
      }
    }

    return null;
  }
  /**
   * Generates hash values, by hashing the valueToEncode using the requests's "alg" parameter, then
   * returning the base64url encoding of the leftmost half of the returned bytes. Used for both
   * at_hash and c_hash claims.
   */
  private String generateHash(
      String algorithm, String valueToEncode, OAuth2ProviderSettings providerSettings)
      throws ServerException {

    if (!providerSettings.getSupportedIDTokenSigningAlgorithms().contains(algorithm)) {
      logger.message("Unsupported signing algorithm requested for hash value.");
      return null;
    }

    final JwsAlgorithm alg = JwsAlgorithm.valueOf(algorithm);

    MessageDigest digest;
    try {
      digest = MessageDigest.getInstance(alg.getMdAlgorithm());
    } catch (NoSuchAlgorithmException e) {
      logger.message("Unsupported signing algorithm chosen for hashing.");
      throw new ServerException("Algorithm not supported.");
    }

    final byte[] result = digest.digest(valueToEncode.getBytes(Utils.CHARSET));
    final byte[] toEncode = Arrays.copyOfRange(result, 0, result.length / 2);

    return Base64url.encode(toEncode);
  }