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 类型调试问题,所以这不是问题所在。
到目前为止,我已经尝试了这些但没有成功:
- 复制用户代理
- 复制每一个 HTTP header (Host, Accept, Content-Type, User-Agent, Accept-Encoding, Connection, 甚至 Content-Length 与表单数据相同)
- 仔细检查keycloak登录是否成功-是的,只是它使用了错误的签名算法
那么keycloak是如何确定使用哪种算法对令牌进行签名的呢?如果每个版本都不一样,我应该在keycloak的代码中寻找答案?
编辑:澄清登录流程以及后端处理它的原因。
如果用户登录,会发生以下情况:
- 客户端--[登录数据]--> keycloak 服务器
- keycloak 服务器--[使用直接令牌授予访问和刷新令牌]--> 客户端
- 客户端--[访问令牌]-->应用服务器
- (应用服务器验证访问令牌)
- 应用服务器--[数据]-->客户端
但在某些情况下,第五步的data是我领域中存在的用户列表。这个问题是keycloak需要一个人有 view-users 角色来列出用户,这只存在于 master 领域,所以我不能使用登录用户的令牌来检索它。
对于这种情况,我在具有 view-users 角色的 master 领域中创建了一个特殊的服务用户,并像这样获取数据:
- 客户端--[请求用户列表]-->应用服务器
- 应用服务器--[服务用户的登录数据]--> keycloak服务器
- keycloak 服务器--[直接授予的访问令牌]-->app 服务器
- app server --[access token]--> keycloak server's get user list API endpoint
- (应用服务器将详细的用户数据过滤为用户名列表)
- 应用服务器--[用户列表]-->客户端
这使得用户名列表有效 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
.
毕竟,如果你这样做,你就不必担心令牌签名或类似的事情。这是根据方案、流程和涉及的各方自动处理的。我相信,如果错误地使用流程,您最终将不得不处理棘手的令牌问题。根据我的说法,这是根本原因,它比关注签名问题更有帮助。你怎么看?
我是漏掉了什么还是完全错了...?
你告诉我。
我正在编写一个使用 keycloak 作为其用户身份验证服务的应用程序。我有普通用户,他们从前端(Web 浏览器)登录到 keycloak,还有服务用户,他们从后端(IIS 上的PHP)登录。但是,当我从后端登录时,keycloak 使用 HS256 作为访问令牌的签名算法,因此拒绝进一步通信,因为在领域和客户端设置中设置了 RS256。为了解决这个问题,我想“假装是前端”为我的服务用户获取 RS256 签名的访问令牌。
出于安全原因,我无法将 HS256 密钥提供给应用服务器,因为它是对称的,太多人可以访问服务器的代码。
我目前正在前端和后端使用相同的 user/pw/client id/grant 类型调试问题,所以这不是问题所在。
到目前为止,我已经尝试了这些但没有成功:
- 复制用户代理
- 复制每一个 HTTP header (Host, Accept, Content-Type, User-Agent, Accept-Encoding, Connection, 甚至 Content-Length 与表单数据相同)
- 仔细检查keycloak登录是否成功-是的,只是它使用了错误的签名算法
那么keycloak是如何确定使用哪种算法对令牌进行签名的呢?如果每个版本都不一样,我应该在keycloak的代码中寻找答案?
编辑:澄清登录流程以及后端处理它的原因。
如果用户登录,会发生以下情况:
- 客户端--[登录数据]--> keycloak 服务器
- keycloak 服务器--[使用直接令牌授予访问和刷新令牌]--> 客户端
- 客户端--[访问令牌]-->应用服务器
- (应用服务器验证访问令牌)
- 应用服务器--[数据]-->客户端
但在某些情况下,第五步的data是我领域中存在的用户列表。这个问题是keycloak需要一个人有 view-users 角色来列出用户,这只存在于 master 领域,所以我不能使用登录用户的令牌来检索它。
对于这种情况,我在具有 view-users 角色的 master 领域中创建了一个特殊的服务用户,并像这样获取数据:
- 客户端--[请求用户列表]-->应用服务器
- 应用服务器--[服务用户的登录数据]--> keycloak服务器
- keycloak 服务器--[直接授予的访问令牌]-->app 服务器
- app server --[access token]--> keycloak server's get user list API endpoint
- (应用服务器将详细的用户数据过滤为用户名列表)
- 应用服务器--[用户列表]-->客户端
这使得用户名列表有效 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
.
毕竟,如果你这样做,你就不必担心令牌签名或类似的事情。这是根据方案、流程和涉及的各方自动处理的。我相信,如果错误地使用流程,您最终将不得不处理棘手的令牌问题。根据我的说法,这是根本原因,它比关注签名问题更有帮助。你怎么看?
我是漏掉了什么还是完全错了...? 你告诉我。