如何设置公钥以从 Keycloak 验证 JWT 令牌?

Bun*_*nyk 5 rsa jwt keycloak

我正在编写后端微服务,它接收来自前端的请求,其中包含Authorisation: Bearer ...从 keycloak(在 docker 容器内)获得的令牌。

我从领域设置的 Keys 部分获得了 RSA 公钥来验证该令牌的签名,但似乎当带有 keycloak 的容器重新启动时,它会重新生成一对密钥,并且我在服务配置中设置的公钥变得无效。

从keycloak使用RSA公钥的正确方法是什么?有没有办法将它配置为使用一对固定的密钥对领域?领域导出时是否导出密钥?或者我必须使用 url like 从 keycloak 获取公钥http://keycloak:8080/auth/realms/:realm_name:,我宁愿不这样做,因为这会增加 keycloak 和后端之间的依赖关系。

mar*_*kas 6

您应该根据颁发者身份服务器的/.well-known/jwks端点验证 JWT 令牌的签名。

1) 查询颁发者身份服务器的/.well-known/jwks端点(JWKS 代表 JSON Web Key Set)

2) 从 JWKS 获取与我们正在验证kidBearer令牌具有相同(密钥 ID)的 JWK(JSON Web 密钥)。要从kid您的 JWT 令牌中获取 ,请首先使用jwt.io的调试器工具对其进行解码。

3)只要身份服务器颁发的令牌通过非对称加密算法(例如:RS256)进行验证,我们就可以仅使用公钥验证签名(因此您不需要私钥)

4) 可以从 JWK 中检索公钥(它是x5cJWK JSON 中的条目)

5)Bearer使用此公钥验证 JWT令牌的签名。

例如,在 Java 中,您可以这样验证:

// verify JWT signature based on Access Identity's JWKS RSA public key (RS256)
try {

  Jwk jwk = new UrlJwkProvider(new URL(issuer + Constants.JWKS_ENDPOINT)).get(decodedJWT.getKeyId());
  final PublicKey publicKey = jwk.getPublicKey();

  if (!(publicKey instanceof RSAPublicKey)) {
    throw new IllegalArgumentException("Key with ID " + decodedJWT.getKeyId() + " was found in JWKS but is not a RSA-key.");
  }

  Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) publicKey, null);
  JWTVerifier verifier = JWT.require(algorithm)
      .withIssuer(issuer)
      .build(); //Reusable verifier instance

  verifier.verify(bearerToken);

  LOGGER.info("Token verified!");

} catch (Exception e) {
  LOGGER.error(e.getMessage());
  throw new InvalidAccessTokenException("JWTVerificationException - Invalid token signature.");
}
Run Code Online (Sandbox Code Playgroud)

  • 问题是“http://localhost:8080/auth/realms/my-realm/.well-known/jwks”和“http://localhost:8080/auth/realms/my-realm/.well-known” /jwks.json` 都是 keycloak 服务器上的 404。(它应该有“.json”扩展名,对吧?) (3认同)
  • 但是, `new UrlJwkProvider(new URL("http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/certs"))` 有效。谷歌也没有“.well-known/jwks” - 所以我不知道它有多“众所周知”...... (2认同)
  • 不过,它们都有一个“.well-known/openid-configuration”。这将返回一个包含“jwks_url”字段的对象。对于 Keycloak,jwks url 将为 `/auth/realms/master/protocol/openid-connect/certs"` (2认同)