// .withAudience(ap) TODO verify audience if the app id
private Optional<DecodedJWT> authenticateRequest(HttpServletRequest req, HttpServletResponse resp) {
        String authHeader = StringUtil.trimToEmpty(req.getHeader("Authorization"));
        String authBearerToken = authHeader.replaceFirst("^Bearer ", "");
        if (authHeader.isEmpty()) {
            LOG.warn("No Authorization header in request");
            resp.setStatus(HTTP_FORBIDDEN);
            return Optional.empty();
        }
        if (authBearerToken.isEmpty()) {
            LOG.warn("No Authorization Bearer token in request");
            resp.setStatus(HTTP_FORBIDDEN);
            return Optional.empty();
        }
        DecodedJWT decodedJWT = JWT.decode(authBearerToken);
        RSAKeyProvider keyProvider = new RSAKeyProvider() {
            @Override
            public RSAPublicKey getPublicKeyById(String keyId) {
                Optional<JSONWebKey> key = jwtKeyProvider.getKey(keyId);
                if (!key.isPresent()) {
                    // TODO what do?
                    resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    return null;
                }
                try {
                    // https://github.com/auth0/jwks-rsa-java/blob/master/src/main/java/com/auth0/jwk/Jwk.java#L171
                    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
                    JSONWebKey jwk = key.get();
                    BigInteger modulus = new BigInteger(1, Base64.getUrlDecoder().decode(jwk.n));
                    BigInteger exponent = new BigInteger(1, Base64.getUrlDecoder().decode(jwk.e));
                    return (RSAPublicKey) keyFactory.generatePublic(new RSAPublicKeySpec(modulus, exponent));
//                    String keyDataString = key.get().x509CertificateChain.get(0);
//                    byte[] keyData = Base64.getDecoder().decode(keyDataString.getBytes(StandardCharsets.UTF_8));
//                    return (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(keyData));
                } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
                    throw new RuntimeException(e);
                }
            }
            @Override
            public RSAPrivateKey getPrivateKey() {
                return null;
            }
            @Override
            public String getPrivateKeyId() {
                return null;
            }
        };
        Algorithm algorithm;
        switch (decodedJWT.getAlgorithm()) {
            case "RS256":
                algorithm = Algorithm.RSA256(keyProvider);
                break;
            default:
                resp.setStatus(HTTP_BAD_REQUEST);
                LOG.error("Unknown algorithm {}", decodedJWT.getAlgorithm());
                return Optional.empty();
        }
        JWTVerifier jwtVerifier = JWT.require(algorithm)
                .acceptLeeway(Duration.ofMinutes(5).getSeconds())
                .withIssuer("https://api.botframework.com")
                // .withAudience(ap) TODO verify audience if the app id
                .build();
        jwtVerifier.verify(authBearerToken);
        return Optional.of(decodedJWT);
    }
.acceptLeeway(Duration.ofMinutes(5).getSeconds())
.withIssuer("https://api.botframework.com")
// .withAudience(ap) TODO verify audience if the app id
.build();
jwtVerifier.verify(authBearerToken);
algorithm = Algorithm.RSA256(keyProvider);
break;
default:
resp.setStatus(HTTP_BAD_REQUEST);
LOG.error("Unknown algorithm {}", decodedJWT.getAlgorithm());
return Optional.empty();
}
JWTVerifier jwtVerifier = JWT.require(algorithm)
.acceptLeeway(Duration.ofMinutes(5).getSeconds())
.withIssuer("https://api.botframework.com")
// .withAudience(ap) TODO verify audience if the app id
.build();
jwtVerifier.verify(authBearerToken);
return Optional.of(decodedJWT);
}
return null;
}
@Override
public String getPrivateKeyId() {
return null;
}
};
Algorithm algorithm;
switch (decodedJWT.getAlgorithm()) {
case "RS256":
algorithm = Algorithm.RSA256(keyProvider);
break;
default:
resp.setStatus(HTTP_BAD_REQUEST);
LOG.error("Unknown algorithm {}", decodedJWT.getAlgorithm());
return Optional.empty();
}
JWTVerifier jwtVerifier = JWT.require(algorithm)
.acceptLeeway(Duration.ofMinutes(5).getSeconds())
.withIssuer("https://api.botframework.com")
// .withAudience(ap) TODO verify audience if the app id
.build();
jwtVerifier.verify(authBearerToken);
return Optional.of(decodedJWT);
}