获取 Keycloak 的公钥

Tho*_*ann 15 keycloak

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

我们已经使用类似于这篇文章的 oauth2 spring 服务器保护了我们的 rabbitmq 和 rest 端点。但它没有我们需要和想要的所有功能。所以我们想使用 Keycloak。通过转到新版本的 spring security 5.1 并指定 security.oauth2.resource.jwk.key-set-uri 并设置必要的依赖项和配置,我已经成功地保护了其余端点。

在尝试保护 RabbitMQ 时,我在检查消息头中的承载令牌时遇到了问题,因为 keycloak 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"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

根据我的理解,密钥为“n”的字段应该是 RSA256 密钥。将它添加到 RSAVerifier 最终会得到一个错误:“Caused by: org.springframework.security.jwt.codec.InvalidBase64CharacterException: Bad Base64 input character decimal 95 in array position 2.”

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

密钥是否已编码?我试过做一个 Base64Utils.decodeFromUrlSafeString 和一个 Base64Utils.decodeFromString。第一个返回更小的东西并且不像键那样 lool,然后创建一个 Illegal 参数异常 Illegal base64 字符 5f。

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

Céd*_*let 26

密钥也直接位于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
}
Run Code Online (Sandbox Code Playgroud)

  • 我真的希望这能得到更好的记录。这会节省我很多时间。谢谢您的回答。 (3认同)
  • @“Thomas Lann”我在测试时偶然发现了它,你是对的,它并没有真正做广告,这也意味着我真的不知道它是否会留下来。 (2认同)
  • 知道如何获取公钥的过期时间吗?我认为它最终应该旋转。我从 keycloak 的 UI 中检查了证书,您可以在其中手动获取公钥,证书有效期为 10 年。但这并不是说在此之前它不会改变。我预计几年后会出现一次无法解释的短暂中断。:-/ 现在我每次只缓存 15m 的密钥。 (2认同)
  • 你知道Java客户端如何调用这个端点吗?我正在使用“keycloak-admin-client”,当我调用“keycloak.realm(realm).toRepresentation().getPublicKey()”时,它给出 null 值。我检查过,它调用“/admin/realms/realmname”,而不是“/auth/realms/realmname”。 (2认同)
  • 好的,我找到了:`keycloak.realm(realm).keys().getKeyMetadata().getKeys()` (2认同)

小智 8

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

  • 打开管理控制台
  • 选择领域
  • 选择领域设置
  • 打开标签“键”
  • 打开标签“活动”
  • 在“公钥”列中按“公钥” 在此处输入图片说明
  • 出现一个带有公钥的弹出窗口。