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

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

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

此流程的目标是最简单的,以吸引不习惯 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

谢谢!

【问题讨论】:

    标签: keycloak keycloak-services keycloak-rest-api


    【解决方案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问题依然存在。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-11-16
        • 2017-07-26
        • 2017-01-21
        • 2019-09-29
        • 2015-11-28
        • 2016-09-13
        • 1970-01-01
        相关资源
        最近更新 更多