获取Keycloak的公钥

时间:2019-01-23 01:05:21

标签: keycloak

我意识到这个问题有很多重复。但我似乎无法正确理解答案。

我们已经使用oauth2 spring服务器similar to this post保护了Rabbitmq和rest端点。但是它没有我们需要和想要的所有功能。因此,我们想使用Keycloak。通过转到新版本的Spring Security 5.1并指定security.oauth2.resource.jwk.key-set-uri并设置必要的依赖项和配置,我已经成功地保护了其余端点。

在尝试保护RabbitMQ时,由于密钥库jwks端点未返回真正的RSA公钥,我一直在从消息头检查承载令牌时遇到问题。

RabbitMQ使用CustomMessageListenerContainer从消息头获取令牌,并使用DefaultTokenServices检查令牌。

据我了解,使用密钥响应的端点是https://keycloak-server/auth/realms/my-realm/protocol/openid-connect/certs 在此端点上执行HttpGet,我得到的响应如下所示

{
    "keys": [{
            "kid": "7JUbcl_96GNk2zNh4MAORuEz3YBuprXilmTXjm0gmRE",
            "kty": "RSA",
            "alg": "RS256",
            "use": "sig",
            "n": "nE9gEtzZvV_XisnAY8Hung399hwBM_eykZ9J57euboEsKra8JvDmE6w7SSrk-aTVjdNpjdzOyrFd4V7tFqev1vVJu8MJGIyQlbPv07MTsgYE5EPM4DxdQ7H6_f3vQjq0hznkFvC-hyCqUhxPTXM5NgvH86OekL2C170xnd50RLWw8FbrprP2oRjgBnXMAif1Dd8kwbKKgf5m3Ou0yTVGfsCRG1_LSj6gIEFglxNHvGz0RejoQql0rGMxcW3MzCvc-inF3FCafQTrG5eWHqp5xXEeMHz0JosQ7BcT8MVp9lHT_utiazhQ1uKZEb4uoYOyy6mDDkx-wExpZkOx76bk_Yu-N25ljY18hNllnV_8gVMkX46_vcc-eN3DRZGNJ-Asd_sZrjbXbAvBbKwVxZeOTaXiUdvl8O0G5xX2xPnS_WA_1U4b_V1t28WtnX4bqGlOejW2kkjLvNrpfQ5fnvLjkl9I2B16Mbh9nS0LJD0RR-AkBsv3rKEnMyEkW9UsfgYKLFKuH32x_CXi9uyvNDas_q8WS3QvYwAGEMRO_4uICDAqupCVb1Jcs9dvd1w-tUfj5MQOXB-srnQYf5DbFENTNM1PK390dIjdLJh4k2efCJ21I1kYw2Qr9lHI4X2peTinViaoOykykJiol6LMujUcfqaZ1qPKDy_UnpAwGg9NyFU",
            "e": "AQAB"
        }
    ]
}

据我了解,密钥为“ n”的字段应该是RSA256密钥。将其添加到RSAVerifier中最终会出现错误“由于:org.springframework.security.jwt.codec.InvalidBase64CharacterException:数组位置2中错误的Base64输入字符十进制95”。

但是,如果我登录到keycloak管理页面并进入领域设置->键并单击公钥,则会弹出一个弹出窗口,显示公钥减去“ ----- BEGIN PUBLIC KEY -----”。和“ ----- END PUBLIC KEY -----”的页眉和页脚。硬编码使一切正常工作。

密钥是否编码? 我试图做一个Base64Utils.decodeFromUrlSafeString和Base64Utils.decodeFromString。第一个返回较小的东西,不会像键那样松散,而第二个返回的结果则创建了一个非法参数异常,非法base64字符5f。

更新: 返回的n是模数,e是公用密钥的公用指数。但是,如何获得实际的钥匙串呢?

4 个答案:

答案 0 :(得分:2)

密钥也直接位于https://keycloak-server/auth/realms/my-realm上,其格式可直接用于您的代码:

{
  "realm": "my-realm",
  "public_key": "MIIBI...",
  "token-service": "https://keycloak-server/auth/realms/my-realm/protocol/openid-connect",
  "account-service": "https://keycloak-server/auth/realms/my-realm/account",
  "tokens-not-before": 0
}

答案 1 :(得分:1)

这里有toIntegerBytes before base64 encode,所以它不仅仅是base64解码。试试:

BigInteger modulus = new BigInteger(1, Base64.decodeBase64("n-value-here"));
BigInteger exponent = new BigInteger(1, Base64.decodeBase64("e-value-here"));

答案 2 :(得分:1)

我还会在以下位置找到它:

  • 打开管理控制台
  • 选择领域
  • 选择领域设置
  • 打开标签“键”
  • 打开“活动”标签
  • 在“公钥”列中,按“公钥enter image description here
  • 出现带有公共密钥的弹出窗口。

答案 3 :(得分:0)

JWKS 端点被设计为随着时间的推移改变它们的密钥(在一个名为 key rotation 的过程中),因此按照 the accepted answer 检索公钥不是一个好主意 .您应该选择使用 JWKS 客户端。我使用 node-jwks-rsa,但同样的创建者也有一个 java 实现 (jwks-rsa-java)。