在 Spring Boot 中使用 Keycloak 实现 JWT、JWE 和 JWS(签名 JWT)

Posted

技术标签:

【中文标题】在 Spring Boot 中使用 Keycloak 实现 JWT、JWE 和 JWS(签名 JWT)【英文标题】:Implementing JWT, JWE and JWS (signed JWT) with Keycloak in Spring Boot 【发布时间】:2018-03-27 14:15:50 【问题描述】:

我尝试使用 Spring Boot 和 Keycloak 作为 AuthService 实现一个简单的 OAuth2“带有签名 JWT 的客户端身份验证”演示应用程序。

想法是:

    一个安全的 REST 服务“生产者” 为角色为“read_person”的所有用户/主体提供端点 GET /person 为角色为“write_person”的所有用户/主体提供端点 POST /person 另一个(不安全的)REST 服务“消费者” 提供对所有人开放的 enpoint /api 通过Feignclient 调用内部“生产者”,使用 RequestInterceptor 传递 AccessToken(签名的 JWT / JWS)

我阅读了有关文档:

http://www.keycloak.org/docs/latest/securing_apps/topics/oidc/java/client-authentication.html

说:

一旦客户端应用程序启动,它允许使用http://myhost.com/myapp/k_jwks 等URL 以JWKS 格式下载其公共> 密钥,>假设http://myhost.com/myapp 是您的客户端> 应用程序的基本URL。这个 URL 可以被 Keycloak 使用(见下文)。

在身份验证期间,客户端生成一个 JWT 令牌并使用 >其私钥对其进行签名,然后在 client_assertion >参数中的特定反向通道 >request(例如,代码到令牌请求)中将其发送到 Keycloak。

我在谷歌上搜索了很多关于这个主题的教程/演示或文档,但到目前为止都失败了。 所以这里是我的问题:

    如何实现这个“k_jwk”端点?我是否可以自己在“制作人”中简单地构建一个@RestController?如何配置 Keycloak 以了解此 URL?

    如何实现我的“消费者”以从 Keycloak 获取新签名的 JWT?

更新 删除了恼人的 PS 声明。

【问题讨论】:

既然我们已经在 Spring Boot Adapter 中实现了,为什么还要重新实现所有这些? 请在这里告诉我如何使用 Keycloak 适配器。我找不到任何演示或文档。 keycloak.org/docs/latest/securing_apps/topics/oidc/java/… ,请查看我的博文developers.redhat.com/blog/2017/05/25/… 或我们的快速入门github.com/keycloak/keycloak-quickstarts 我在您的博客或这些快速入门中找不到任何有关使用签名 JWT 的文档。 好吧,它没有记录,因为它是在内部完成的,如果你使用适配器,你不必关心这个,如果你想重新实现我们的适配器所做的检查 Keycloak 项目的源代码。 【参考方案1】:

    您不需要实现 k_jwk 端点,这是由适配器处理的。默认情况下,Keycloak 将查看 http:///your.app.com/k_jwk(但如果需要,您可以在控制台中覆盖它)。 然后你需要配置你的 Spring Boot 客户端,只需使用与 keycloak.json 相同的属性,但格式为 application.properties:

    ...

    keycloak.credentials.jwt.client-keystore-file=classpath:keystore-client.jks keycloak.credentials.jwt.client-keystore-type=JKS

    等等……

    您需要一个令牌来调用producer,但正如您所说,入口点将是一个不安全的端点,因此您可能希望为此使用Service Account。

我希望这会有所帮助。

【讨论】:

好的,谢谢。第一个信息非常方便。我将尝试理解并实施此服务帐户主题。 我可能需要进一步的帮助。我使用正确的 keycloak 设置和 gradle 依赖项中的适配器设置了一个客户端应用程序。我创建了一个 Feign 客户端(RestTemplate 对我来说也可以)。怎么办?如何生成 JWT?我不明白服务帐户的提示。文档说:keycloak.org/docs/2.5/server_admin/topics/clients/oidc/… 总结:通过 POST /auth/realms/demo/protocol/openid-connect/token 从 keycloak 获取令牌,所以我必须自己写这个? 是的,如果您想使用签名的 JWT 作为客户端身份验证,可能需要做一些手动工作,但您可以利用此类获取 jwt 令牌github.com/keycloak/keycloak/blob/master/adapters/oidc/…【参考方案2】:

更新

我无法解决这个问题,但同时学到了一些关于singned JWT的东西:

    通过自己创建一个包含所有必要声明(sub、nbf、exp ...)的 Json 结构并使用来自 Keycloak 的 JKS/私钥对其进行签名/认证,从而创建一个所谓的“不记名令牌”。 Keycloak 旁边有一些不错的第三方库可以做到这一点。

    要从 Keycloak 获取真正的 AccessToken (JWE/JWS):在 /auth/realms/$realm/protocol/openid-connect/token/introspect 处将此静态最终承载令牌发送到 Keycloak em>

使用查询参数:

grant_type=client_credentials&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=$BEARER_TOKEN

    使用接收到的真实AccessToken访问ResourceServer...

【讨论】:

我有一个类似的问题,所以你能展示一段代码来使用 jwt 和 spring boot 从 keycloak 获取令牌吗?请.. PS如果你想要这是我的问题:https://***.com/questions/49900124/can-i-pass-a-principal-with-rest-template-if-im-using-an-async-task-wiht-spring

以上是关于在 Spring Boot 中使用 Keycloak 实现 JWT、JWE 和 JWS(签名 JWT)的主要内容,如果未能解决你的问题,请参考以下文章

Grails、Spring Security 和 Keycloak:表单以 ISO-8859-1 而不是 UTF-8 提交

spring-boot实战12:Spring Boot中使用JavaMailSender发送邮件

Spring Boot:在Spring Boot中使用Mysql和JPA

在 spring-boot 项目中使用 spring mvc xml 项目

Spring boot在Spring boot中Redis的使用

如何在 spring-boot 中禁用 spring-data-mongodb 自动配置