keycloak如何确定使用哪种签名算法?

How does keycloak determine which signature algorithm to use?

我正在编写一个使用 keycloak 作为其用户身份验证服务的应用程序。我有普通用户,他们从前端(Web 浏览器)登录到 keycloak,还有服务用户,他们从后端(IIS 上的PHP)登录。但是,当我从后端登录时,keycloak 使用 HS256 作为访问令牌的签名算法,因此拒绝进一步通信,因为在领域和客户端设置中设置了 RS256。为了解决这个问题,我想“假装是前端”为我的服务用户获取 RS256 签名的访问令牌。

出于安全原因,我无法将 HS256 密钥提供给应用服务器,因为它是对称的,太多人可以访问服务器的代码。

我目前正在前端和后端使用相同的 user/pw/client id/grant 类型调试问题,所以这不是问题所在。

到目前为止,我已经尝试了这些但没有成功:

那么keycloak是如何确定使用哪种算法对令牌进行签名的呢?如果每个版本都不一样,我应该在keycloak的代码中寻找答案?

编辑:澄清登录流程以及后端处理它的原因。

如果用户登录,会发生以下情况:

  1. 客户端--[登录数据]--> keycloak 服务器
  2. keycloak 服务器--[使用直接令牌授予访问和刷新令牌]--> 客户端
  3. 客户端--[访问令牌]-->应用服务器
  4. (应用服务器验证访问令牌)
  5. 应用服务器--[数据]-->客户端

但在某些情况下,第五步的data是我领域中存在的用户列表。这个问题是keycloak需要一个人有 view-users 角色来列出用户,这只存在于 master 领域,所以我不能使用登录用户的令牌来检索它。
对于这种情况,我在具有 view-users 角色的 master 领域中创建了一个特殊的服务用户,并像这样获取数据:

  1. 客户端--[请求用户列表]-->应用服务器
  2. 应用服务器--[服务用户的登录数据]--> keycloak服务器
  3. keycloak 服务器--[直接授予的访问令牌]-->app 服务器
  4. app server --[access token]--> keycloak server's get user list API endpoint
  5. (应用服务器将详细的用户数据过滤为用户名列表)
  6. 应用服务器--[用户列表]-->客户端

这使得用户名列表有效 public,但所有其他数据仍然对客户端隐藏 - 由于 security/privacy 原因,我想保持这种方式,所以我可以' t只是将服务用户的登录数据放在前端的JS变量中。

在后一个列表中,第 4 步失败,因为第 3 步 returns HS256 签名访问令牌。在前面的列表中,第 2 步正确 returns 一个 RS256 签名的访问令牌。

感谢您的澄清。如果可以的话,我可能会以不同于预期的方式回答您的问题。当您专注于令牌签名算法时,我认为您的 OAuth2 流程中关于它们的使用存在错误,或者您面临一些误解。

后端和前端都使用引用 OAuth2 流程的“直接访问授权”这一事实 Resources Owner Credentials Grant 要么是错误的声明,要么是错误的你的架构。

如 Keycloak 自己的文档所述(但在官方 OAuth.2 参考资料中也略有不同):

Resource Owner Password Credentials Grant (Direct Access Grants) ... is used by REST clients that want to obtain a token on behalf of a user. It is one HTTP POST request that contains the credentials of the user as well as the id of the client and the client’s secret (if it is a confidential client). The user’s credentials are sent within form parameters. The HTTP response contains identity, access, and refresh tokens.

据我所知,您描述的应用程序和用例不需要此流程。

我的提议

相反,我在您的流程 (1) 案例中看到的是 授权码流程 ...

  • 假设“客户端”是指浏览器中的普通用户(从您的前端应用程序重定向到 Keycloak auth)
  • 并假设您实际上不需要客户端中的 ID 和访问令牌,除非您有正当合理的理由。由于允许的流量被认为是 legacy/deprecated,因此不再推荐。在这种情况下,我们会说 Implicit Flow(现在也不鼓励使用 Password Grant 流)。

所以我认为所提供的交换(第一个序列在你的 post 中的点 1 到 5)在某些时候是无效的。


对于第二个流程(后端 -> 列出用户),我建议进行两个修改:

  • 允许用户轮询前端应用程序以获取用户列表,然后前端会要求后端 return 它。具有 view-roles 客户端服务帐户的后端将能够获取所需数据:

     Client (logged) --> Request list.users to FRONTEND app --> Get list.users from BACKEND app
                                                                   (<--> Keycloak Server)
                     <----------------------------------------- Return data.
    
  • 使用 Client Credentials Grant(流程)用于此用例的后端 <> Keycloak 交换。该应用程序将有一个 service account,您可以为其分配特定的范围+角色。它不会代表任何用户工作(即使您可以通过其他方式检索原始请求者!),但会以完全安全的方式完成工作并保持简单。您甚至可以为这些交换定义特定的 Client,即 bearer-only.


毕竟,如果你这样做,你就不必担心令牌签名或类似的事情。这是根据方案、流程和涉及的各方自动处理的。我相信,如果错误地使用流程,您最终将不得不处理棘手的令牌问题。根据我的说法,这是根本原因,它比关注签名问题更有帮助。你怎么看?

我是漏掉了什么还是完全错了...? 你告诉我。