Keycloak:实现“重置密码”(作为管理员)流程与“忘记密码”(作为用户)相同

Posted

技术标签:

【中文标题】Keycloak:实现“重置密码”(作为管理员)流程与“忘记密码”(作为用户)相同【英文标题】:Keycloak : implement "reset password" (as admin) flow same as "forgot password" (as user) 【发布时间】:2021-06-25 22:08:19 【问题描述】:

我想在 Keycloak 中实现这个身份验证流程:

    用户仅通过输入电子邮件来创建帐户 用户已登录并可以访问我的服务 2'。同时,会向他发送一封电子邮件,让他“完成”他的帐户 用户离开他的会话 -> 要重新使用我的服务,他必须点击收到的电子邮件 通过点击收到的电子邮件,用户定义了他的第一个密码 然后用户会自动登录(无需通过登录页面)。

此流程的目标是最简单的,以吸引不习惯 web 应用的用户。

我会做的实现:

创建一个无需密码请求的帐户:我通过禁用 Password ValidationProfile Validation 规则来自定义 Keycloak Registration 流程 以编程方式,在我的 web 应用程序中,在用户第一次连接时,通过 REST 管理 API,我触发电子邮件操作 UPDATE_PASSWORD

我得到了一些有用的东西,但是:

A.通过电子邮件收到的链接重定向到确认执行操作的中间页面(“执行以下操作”)-(类似于Keycloak Implement Reset password flow same as forgot password flow)

B.然后用户被重定向到登录页面,而不是直接连接到应用程序。

当我作为普通用户触发重置密码请求(通过“忘记密码”功能)时,该过程就是我想要的:通过单击电子邮件链接,我直接进入允许我输入的页面并确认新密码,然后我就通过了身份验证。

我的问题:您是否看到了实现这种“简化”流程的方法?

我的 keycloak 版本:11.0.2

谢谢!

【问题讨论】:

【参考方案1】:

我可以删除“info.ftl”页面显示,自定义“ExecuteActionsActionTokenHandler”,如下所述:

action-token-spi

你必须创建一个文件:

src/main/resources/META-INF/services/org.keycloak.authentication.actiontoken.ActionTokenHandlerFactory

包含您要使用的类的名称:

com.example.ExecuteActionTokenHandlerFactory

然后您使用以下代码创建该类 com.example.ExecuteActionTokenHandlerFactory:

public class ExecuteActionTokenHandlerFactory extends ExecuteActionsActionTokenHandler 


    @Override
    public Response handleToken(ExecuteActionsActionToken token, ActionTokenContext<ExecuteActionsActionToken> tokenContext) 
        AuthenticationSessionModel authSession = tokenContext.getAuthenticationSession();
        String redirectUri = RedirectUtils.verifyRedirectUri(tokenContext.getUriInfo(), token.getRedirectUri(),
                tokenContext.getRealm(), authSession.getClient());

        if (redirectUri != null) 
            authSession.setAuthNote(AuthenticationManager.SET_REDIRECT_URI_AFTER_REQUIRED_ACTIONS, "true");

            authSession.setRedirectUri(redirectUri);
            authSession.setClientNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUri);
        

        token.getRequiredActions().stream().forEach(authSession::addRequiredAction);

        UserModel user = tokenContext.getAuthenticationSession().getAuthenticatedUser();
        // verify user email as we know it is valid as this entry point would never have gotten here.
        user.setEmailVerified(true);

        String nextAction = AuthenticationManager.nextRequiredAction(tokenContext.getSession(), authSession, tokenContext.getClientConnection(), tokenContext.getRequest(), tokenContext.getUriInfo(), tokenContext.getEvent());
        return AuthenticationManager.redirectToRequiredActions(tokenContext.getSession(), tokenContext.getRealm(), authSession, tokenContext.getUriInfo(), nextAction);
    



其实和上层的实现是一样的,只是我们去掉了以下部分:

        if (tokenContext.isAuthenticationSessionFresh()) 
           ...
        

这意味着如果用户没有会话,当用户重置他的密码时,他会被重定向到那个“info.ftl”页面。

【讨论】:

【参考方案2】:

作为问题 A 的解决方法,我自定义了info.ftl 模板页面。我在链接上向click 添加了一个丑陋的内联脚本,自动重定向到更新密码页面。

<#import "template.ftl" as layout>
(...)
            <#elseif actionUri?has_content>
              <p><a id="yolo" href="$actionUri">$kcSanitize(msg("proceedWithAction"))?no_esc</a></p>
              <script>document.getElementById('yolo').click()</script>
(...)

在我找到更清洁的解决方案之前,它会完成这项工作。

目前,B问题依然存在。

【讨论】:

以上是关于Keycloak:实现“重置密码”(作为管理员)流程与“忘记密码”(作为用户)相同的主要内容,如果未能解决你的问题,请参考以下文章

keycloak 8 登录更新密码 ftl 文件未加载

Keycloak - 代理后的 URL 重置密码电子邮件

Keycloak - 重置密码时未显示用户未找到的消息信息

KeyCloak 忘记密码 电子邮件链接

如何通过 API 在 keycloak 中忘记密码

生成密码重置 URL