Keycloak公共客户端和授权

Posted

技术标签:

【中文标题】Keycloak公共客户端和授权【英文标题】:Keycloak public client and authorization 【发布时间】:2019-04-06 17:07:11 【问题描述】:

我们正在使用带有 Jetty 的 keycloak-adapter 来使用 Keycloak 进行身份验证和授权。 根据Keycloak doc for OIDC Auth flow:

此流程的另一个重要方面公共与机密客户的概念。保密客户必须 在他们交换临时代码时提供客户秘密 令牌。公共客户端不需要提供此客户端密码。 只要 HTTPS 是严格的,公共客户端就很好 强制执行,并且您对重定向 URI 的内容非常严格 为客户注册。

html5/javascript 客户端总是必须是公共客户端,因为 无法以安全的方式将客户端机密传输给他们 方式。

我们有连接到 Jetty 并使用身份验证的 webapp。因此,我们创建了一个公共客户端,它非常适合 webapp/REST 身份验证。 问题是,一旦我们启用授权,客户端类型就会从 Public 转换为 Confidential,并且不允许将其重置为 Public。现在,我们正在喝汤。由于授权,我们无法拥有公共客户端,也无法将 web 应用程序连接到机密客户端。 这在我们看来似乎是矛盾的。知道为什么客户需要对授权保密吗?对此有任何帮助,我们如何克服这个问题? 谢谢。

【问题讨论】:

请指点这里? 您使用的是哪个 OAuth 流程?是授权码授权、隐式授权还是其他? 这是基于用户名/密码和jwt令牌的正常授权流程。 身份验证代码和隐式流均基于该概念,但创建目的不同。 我认为作为资源服务器的码头应用程序应该是私有的。您的前端客户端应该是公开的,因为有人可以使用客户端并在开发者控制台中查看客户端密码。我认为您的问题需要更多关于手头的架构和问题的信息,然后才能帮助您。 【参考方案1】:

经过深思熟虑,我们发现当您连接到公共客户端时,确实不需要在公共客户端上启用授权。当任何请求到达公共客户端时,它只进行身份验证部分。当实际请求使用机密客户端到达资源服务器(在我们的例子中为 Jetty)时,授权部分就完成了(因为 Jetty 知道其中配置了机密客户端)。

【讨论】:

我还是不明白。机密客户端仍然需要身份验证。如果您仅在公共客户端上进行身份验证,您如何将令牌“传递”给机密客户端?还是您再次进行身份验证? 在keycloak中,您可以将公共客户端连接到机密客户端。这样,公共客户端令牌将与机密客户端一起使用。 @NumeroUno 能否提供更多详细信息,它们如何连接? @NumeroUno 有没有机会详细介绍一下?我试图传递公共客户端收到的访问令牌以访问资源,但由于保护服务评估 JWT 令牌的 azp(issue-for)字段,它尝试在公共客户端上查找资源,没有定义资源:Client application [public-client] is not registered as a resource server. 好的,这相当于authzClient.protection(userJwt)。现在,如果您使用公共客户端进行授权,userJwt 中的 azp 声明将指向公共客户端。如果我将该 userJwt 从公共客户端传递给机密客户端,并让机密客户端向 keycloak 请求 uma 令牌,它会失败,因为令牌是为公共客户端颁发的,并且公共客户端没有配置授权。在您的案例中,如何将上下文从公共客户端切换到机密客户端?【参考方案2】:

我认为您在创建客户端时指的是 Keycloak 管理控制台中的“授权启用”开关。如果您查看标签旁边的问号,您会看到提示“启用/禁用对客户端的细粒度授权支持。

Create client in Keycloak admin console (v 6.0.1)

这适用于为充当资源服务器的后端应用程序创建客户端时。在这种情况下,客户将是保密的。

如果您想为前端应用创建客户端、验证用户并获取 JWT,那么您不需要这个。

另见:https://www.keycloak.org/docs/latest/authorization_services/index.html

【讨论】:

是的,我需要这个。我需要 Keycloak 来授权来自我的 SPA(公共客户端)的请求,这样我就不需要在我的所有资源服务器中重复实现逻辑。我不明白他们为什么不为公共客户端启用授权。【参考方案3】:

据我了解,您的前端和后端应用程序是分开的。如果您的前端是一个静态 Web 应用程序并且不是由同一个后端应用程序(服务器)提供服务,并且您的后端是一个简单的 REST API - 那么您将配置两个 Keycloak 客户端:

public 前端应用程序的客户端。它将负责获取 JWT 令牌。 bearer-only 客户端,将附加到您的后端应用程序。

要启用授权,您将创建角色(领域或客户端范围,从领域级别开始,因为它更容易理解)。然后将在 Keycloak 管理 UI 中为每个用户分配一个角色。基于此,您应该配置您的 keycloak 适配器配置(在后端)。

考虑到所有因素,为了与您的 REST API 通信,您需要将 JWT 令牌附加到 Authorization 标头中的每个 HTTP 请求。根据您的前端框架,您可以使用以下任何一种:

Keycloak js adapter 其他绑定(angular、react)

附:为了调试,我刚刚编写了一个名为 brauzie 的 CLI 工具 这将帮助您获取和分析您的 JWT 令牌(范围、角色等)。它可以用于公共和机密客户。你 也可以使用Postman 和https://jwt.io

HTH :)

【讨论】:

当我在到期时间之前注销(从我的前端应用程序或关闭与 keycloak 管理控制台的会话)时,我的后端 rest api 仍然可以工作是否正确?我在 keycloak 中有一个公共客户端,我的后端应用程序只设置了承载。 您能详细说明一下应该如何配置授权吗?如果 REST API 使用从客户端传递的 JWT 令牌来评估使用 keycloak 的资源访问,我会得到 Client application [public-client] is not registered as a resource server.,因为 keycloak 评估 JWT github.com/keycloak/keycloak/blob/11.0.3/services/src/main/java/… 的 azp(颁发给)字段。

以上是关于Keycloak公共客户端和授权的主要内容,如果未能解决你的问题,请参考以下文章

为啥机密和公共客户端需要应用程序来处理 spring/keycloak 适配器中的会话?

keycloak javascript适配器请求离线令牌

Keycloak 客户端没有可用于访问类型公共的秘密

如何使用从公共客户端发出的令牌查询 keycloak 资源权限

apache shiro:在 shiro.ini 中添加啥以使用 JWT 和 keycloak 作为授权服务器进行客户端身份验证

使用 KeyCloak 的 OAuth2 授权接口