繁体   English   中英

创建 jwks 端点 spring boot

[英]Creating jwks endpoint spring boot

我正在 Java Spring Boot 中构建两个服务应用程序,其中一个服务是生成 jwt 的身份验证服务,另一个是资源服务,它解码 jwt 并根据 jwt 主题返回帖子列表。

我当前的身份验证服务设置有一个存储在资源中的 .jks 密钥对和一个登录端点:

  • 检查用户名是否存在于 MongoDB 中并且密码是否与存储的编码匹配
  • 如果检查通过,则返回一个带有主题中用户名的 jwt

我的资源服务器有一个在 preHandle() 阶段解码 jwt 的方法,如下所示:

@Value("${jwt.key}")
private String publicKey;

public Claims decodeJWT(String jwt) {

    KeyFactory kf;
    PublicKey key;

    publicKey = publicKey
            .replace("-----BEGIN PUBLIC KEY-----", "")
            .replace("-----END PUBLIC KEY-----", "")
            .replace("\n", "")
            .trim();

    try{
        kf = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec pubKeySpecX509EncodedKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
        key = kf.generatePublic(pubKeySpecX509EncodedKeySpec);
    } catch (Exception e) {
        throw new RuntimeException("Failed to generate Public Key", e);
    }

    //This line will throw an exception if it is not a signed JWS (as expected)
    return Jwts.parser()
            .requireIssuer("auth-service")
            .requireAudience("posts-service")
            .setSigningKey(key)
            .parseClaimsJws(jwt).getBody();
}

我唯一的问题是我需要从身份验证服务 .jks 文件中手动导出公钥并将其存储在资源服务 application.yml 文件中。

因此,我的问题是:在身份验证服务中创建 jwks 端点的最佳方法是什么,该端点从 .jks 文件返回公钥? 以及如何最好地从资源服务中添加对它的调用?

干杯克里斯

弄清楚了。

在 auth 服务中创建 JWKS:

    public Map<String, List<Map<String, Object>>> getPublicKeys(){

    RSAPublicKey rsa;

    try{
        is = JwtBuilder.class.getResourceAsStream(("/" + signingKeyStore));
        keyStore = KeyStore.getInstance("JKS");
        keyStore.load(is, signingKeyStorePassword.toCharArray());
        rsa = (RSAPublicKey) keyStore.getCertificate(signingKeyId).getPublicKey();
    } catch (Exception e) {
        throw new RuntimeException("Failed to retrieve public key", e);
    }

    Map<String, Object> values = new HashMap<>();

    values.put("kty", rsa.getAlgorithm()); // getAlgorithm() returns kty not algorithm
    values.put("kid", signingKeyId);
    values.put("n", Base64.getUrlEncoder().encodeToString(rsa.getModulus().toByteArray()));
    values.put("e", Base64.getUrlEncoder().encodeToString(rsa.getPublicExponent().toByteArray()));
    values.put("alg", "RS256");
    values.put("use", "sig");

    List<Map<String, Object>> keyList = new ArrayList<>();

    keyList.add(values);

    Map<String, List<Map<String, Object>>> keys = new HashMap<>();

    keys.put("keys", keyList);

    return keys;
}

在资源服务中解码和验证 JWT:

public DecodedJWT decodeAndVerifyJWT(String token){

    DecodedJWT jwt;

    try{
        jwt = JWT.decode(token);
        JwkProvider provider = new UrlJwkProvider("http://localhost:8090");
        Jwk jwk = provider.get(jwt.getKeyId());
        Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);
        algorithm.verify(jwt);
    } catch (InvalidPublicKeyException e) {
        throw new RuntimeException("Invalid Public key", e);
    } catch (JwkException e) {
        throw new RuntimeException("Couldn't verify JWT", e);
    }

    return jwt;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM