我知道这是一个老问题,但我最近一直在研究类似的问题,因此认为将我的发现分享给其他可能正在研究这个问题并想知道可能性是什么的人可能会很有价值。
TL;DR
您只能真正使用现有的 Keycloak 操作来执行此操作,或者将位于 https://{keycloak server URL}/auth/realms/{realm name}/account 的用户帐户管理页面嵌入 iframe 中。就是这样,我害怕。在我看来,目前最好将操作直接分配给帐户或使用凭据重置电子邮件来分配操作;如果需要,这两个都可以通过 Admin API 完成:
发送包含指定操作的凭据重置电子邮件:
https ://www.keycloak.org/docs-api/11.0/rest-api/index.html#_executeactionsemail
直接在帐户上设置操作(包括您在正文中发送到端点的用户 JSON 的 requiredActions 部分中的操作):
https ://www.keycloak.org/docs-api/11.0/rest-api/index .html#_updateuser
背景是,作为我一直在从事的项目的一部分,我们想看看我们是否可以有一种集成方式让用户在为他们创建新帐户时设置他们的初始密码和 OTP 设备,因为默认方法使用“凭据重置”功能从 Keycloak 向他们发送电子邮件具有以下限制:a) 它不提供指向应用程序本身的链接,除非您覆盖主题,并且如果您为不同用户提供应用程序的多个实例,您无法知道要为哪个实例提供链接,因此最终可能必须包含它们的列表,并且 b) 即使更改了主题,它通常也感觉不是真正的应用程序原生。不过,如果您是明智的,我建议您停止并使用此功能 - 请参阅 TL;
因此,简而言之,没有 API 端点可用于接收 QR 码来设置 OTP 设备。但是,有两个地方可以检索 QR 码 - 当您以已分配给其帐户的“配置 OTP”操作的用户身份登录时的 OTP 设备设置屏幕,以及用户自己的帐户管理屏幕。
配置 OTP 操作屏幕的第一个选项是非启动项。它仅在您登录时显示,因此根据定义,用户必须通过 Keycloak 登录页面登录 Keycloak 才能触发页面显示。此时,您已经在 Keycloak 页面而不是您的应用程序的一个页面上,因此除非您可以通过自定义主题对这些 Keycloak 页面进行更改来获得非常有创意,否则点击此页面并不是一个真正的选择。
第二种选择更有趣,但远非理想。每个登录的用户都可以访问帐户管理页面,该页面位于 https://{keycloak server URL}/auth/realms/{realm name}/account。此页面允许您执行更改姓名、密码等操作,还允许您添加 OTP 设备(如果您还没有 OTP 设备)或删除与您的帐户关联的任何现有 OTP 设备。可以通过 https://{keycloak server URL}/auth/realms/{realm name}/account/totp 直接访问帐户管理页面的此 OTP 设备选项卡。
正如我所提到的,您没有可以访问的 API 来查看此页面上显示的 QR 码。访问它的唯一方法是通过对 https://{keycloak server URL}/auth/realms/{realm name}/account/totp 的 GET 请求,它返回我已经提到的页面的 HTML。好的,那么我们可以通过编程方式抓取 QR 码,然后将其放在我们自己的应用程序页面中吗?呃,不,不是真的。您会看到,虽然许多 Keycloak API 端点正确地允许您在授权标头中发送不记名令牌(例如访问令牌)以访问和端点,但此页面不会接受不记名令牌作为身份验证/授权的手段。相反,它使用锁定到 Keycloak URL 的会话 cookie。当您通过 Keycloak 登录页面登录您的应用程序时,会设置此 cookie,因此,当您导航到该帐户管理页面时,它已经登录,并且由于帐户管理页面使用与原始 Keycloak 登录页面相同的服务器和域名,它可以访问 cookie,并且可以让您in. 此 cookie 不能由您的应用程序发送到例如您自己的 REST API,然后以编程方式调用帐户管理页面并抓取 QR 码,因为出于良好的安全原因,您的应用程序无权访问它。这可能是您可以在某处的 Keycloak 中更改的内容,但如果有的话,我强烈建议您不要更改它。它可以访问 cookie 并允许您进入。此 cookie 不能由您的应用程序发送到例如您自己的 REST API,然后以编程方式调用帐户管理页面并抓取 QR 码,因为您的应用程序无权访问它出于良好的安全原因。这可能是您可以在某处的 Keycloak 中更改的内容,但如果有的话,我强烈建议您不要更改它。它可以访问 cookie 并允许您进入。此 cookie 不能由您的应用程序发送到例如您自己的 REST API,然后以编程方式调用帐户管理页面并抓取 QR 码,因为您的应用程序无权访问它出于良好的安全原因。这可能是您可以在某处的 Keycloak 中更改的内容,但如果有的话,我强烈建议您不要更改它。
那么如果我们不能从我们自己的服务器上抓取页面,我们可以在前端做点什么吗?好吧,如前所述,您的应用程序无权访问会话 cookie,但是如果您在前端 JavaScript 中向帐户管理页面发出请求(例如,使用 fetch 或 axios),那么该请求将连同它一起发送 cookie ,这样可以正常工作吗?嗯,实际上,由于 CORS,您会在这种情况下收到一条错误消息。CORS 是跨域资源共享,为了允许访问 Keycloak 页面,您必须打开服务器上的设置以允许从您的网站地址访问它。我看过一些文章,如果你愿意的话,你可以如何在 Keycloak 上打开你的 CORS 设置,但我会对此感到非常紧张。我不 对 Keycloak 的内部结构及其运作方式知之甚少,无法评论这有多大的安全风险,但我当然不会推荐它。这里有一些信息(Keycloak angular 不存在“Access-Control-Allow-Origin”标头) 更改应用程序的 Keycloak 客户端的“Web Origins”设置,但这会使您的应用程序面临一些严重的潜在滥用。还有一个主要问题是,即使您抓取了 QR 码,设备实际上也不会添加到用户的帐户中(即使它出现在身份验证器应用程序中),直到您在 QR 码所在的页面中输入代码并单击保存。由于没有可用于完成此操作的 API 端点,因此我认为此选项也不可行。我已经尝试过您是否可以在 https://{keycloak server URL}/auth/realms/{realm name}/protocol/openid-connect/token 使用令牌检索端点来查看是否与您的用户名/密码/otp 代码将以某种方式“注册” 您的设备并完成该过程,但是尽管您可以通过这种方式获得令牌,并且它不会抱怨 otp 代码,但它实际上并没有注意到代码,因为就用户帐户而言,它不会t 有一个注册的设备。所以我们必须使用账户管理页面上的表格来完成这个注册过程。
所以可能这样做的最后一种方法是....一个iframe。对不起,是的,这是垃圾,但这是你剩下的全部了。您可以将 iframe 指向您的帐户管理页面,并且由于用户已登录,因此他们将能够从您的应用程序页面中看到内容。您可以使用相对定位、固定宽度和高度以及移除滚动条来确保您只显示二维码以及一次性代码、设备名称和保存/取消按钮的字段。可悲的是,这似乎是目前唯一的选择,并且由于 iframe 通常是多么令人讨厌和不可靠 - 它们肯定不适合您的应用程序,您需要覆盖您的 Keycloak 主题才能获得有问题的页面看起来更像您的应用程序 - 我'
如果你做到了这一点,那么恭喜你,你在 Stack Overflow 上获胜 :-)