【问题标题】:How to enable 2FA using email using keycloak-admin-client in spring boot如何在 Spring Boot 中使用 keycloak-admin-client 使用电子邮件启用 2FA
【发布时间】:2022-06-15 04:00:35
【问题描述】:

我的要求是在 Keycloak 中使用电子邮件启用 2FA。

启用后,如果用户尝试通过电子邮件和密码登录,则在用户成功通过身份验证后,基于时间的令牌将发送到电子邮件。

用户将从自定义 UI 执行此操作,即在我们的产品中,我们有 UI 可以为用户启用/禁用 2FA。

我们正在使用 Keycloak,我们希望使用 Keycloak API 来实现这一目标。

我正在使用 keycloak-admin-client 与 Keycloak API 进行交互,但我没有找到足够的资源来使用 keycloak-admin-client 实现此目的。

我正在寻找一种使用 keycloak-admin-client 如何为用户启用 2FA 的方法。

我们将不胜感激。

谢谢

【问题讨论】:

    标签: keycloak keycloak-rest-api keycloak-admin-client keycloak-spring-boot-starter


    【解决方案1】:

    您应该将自定义 REST 端点添加到 Keycloak,以便能够从您的自定义 UI 启用 2FA。我们以前做过。它并没有那么复杂,但它需要您查看 Keycloak 源代码,以了解激活 OTP 时它在做什么。要检查/使用的一些重要类是 TotpBean、OTPCredentialModel 和 OTPPolicy。

    为了启用 2FA,我们需要在自定义 UI 中显示 QR 码图像。因此,我们向 Keycloak 添加了一个端点,该端点实例化了一个 TotpBean 的实例。它使您可以访问 QR 码图像和生成图像的等效字符串表示所需的秘密值,以便可以在 2FA 应用程序(例如 Google Authenticator)中对其进行扫描/输入。以下是此类端点的示例:

    @GET
    @Produces({MediaType.APPLICATION_JSON})
    @Path("/o2p-enable-config/{email}")
    @NoCache
    public Response fetchOtpEnableConfig(@Email @PathParam("email") String email) {
        UserModel user = session.users().getUserByEmail(email, realm);
        TotpBean totp = new TotpBean(session, realm, user, session.getContext().getUri().getRequestUriBuilder());
    
        return Response
               .ok(new YouOTPResponseClass("data:image/png;base64, " + totp.getTotpSecretQrCode(), totp.getTotpSecret(), totp.getTotpSecretEncoded()))
           .build();
    }
    

    然后在您自己的后端,您调用此端点并将用户的电子邮件发送给它并接收图像和秘密值。您可以在 UI 中按原样显示图像,并将秘密值保留在后端(例如,在用户会话中)。当用户使用应用程序扫描图像并在您的自定义 UI 中输入应用程序提供的 totp 值时,您会将 totp 值和密钥发送到您应该添加到 Keycloak 的另一个端点。第二个端点是对值进行验证并启用 2FA 的端点。

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/enable-2fa/{email}")
    @NoCache
    public Response enable2Fa(@Email @PathParam("email") String email, OtpDetails optDetails) {
        OTPPolicy policy = realm.getOTPPolicy();
        String totp = optDetails.getTotp();
        UserModel user = session.users().getUserByEmail(email, realm);
    
        OTPCredentialModel credential = OTPCredentialModel.createFromPolicy(realm, optDetails.getSecret(), optDetails.getUserLabel());
        if (CredentialValidation.validOTP(totp, credential, policy.getLookAheadWindow())) {
            CredentialHelper.createOTPCredential(session, realm, user, totp, credential);
            return Response.noContent().status(204).build();
        } else {
            return Response.status(BAD_REQUEST).build();
        }
    }
    

    Keycloak 支持每个用户的多个 2FA。这就是为什么它还有一个名为label 的属性,允许用户命名它们,以便在2FA 登录场景中显示给定名称。您还可以允许用户在您的自定义 UI 中输入标签值并将其传递给第二个端点(或者如果您不允许您的用户设置多个 2FA,则只需将一个空值传递给 Keycloak)。

    我知道这看起来很复杂,但实际上并没有那么复杂。 Keycloak 域模型设计得很好,当您熟悉它时,您可以轻松找到您需要做的事情并将其包装在自定义 API 中。 但始终确保公开功能不会损害系统的整体安全模型。

    【讨论】:

      【解决方案2】:

      我同意为此用例编写自定义提供程序是必要的。

      查看https://www.n-k.de/2020/12/keycloak-2fa-sms-authentication.html 和https://www.youtube.com/watch?v=GQi19817fFk 了解如何实现它。

      这是一个通过 SMS 的示例,但通过电子邮件将非常相似,只是改变了将代码发送给用户的方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-12
        • 2023-01-18
        • 2018-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多