首页 > 解决方案 > Keycloak - Multi/2FA Factor - OTP - QR Code - 自定义登录屏幕 - Rest API

问题描述

我有自己的登录页面,用户在其中输入用户名/密码。 此用户名/密码用于通过 Keycloak Rest API 登录。

http://localhost:8080/auth/realms/Demo/protocol/openid-connect/token

input - {username,password,grant_type,client_secret,client_id}

作为回应,我得到了access token

现在我希望启用 Authenticator ( Google Authenticator)。我已经从后端启用了它。现在,如果用户希望通过我的应用程序登录,我的登录页面需要获取以下详细信息。

1.)不知何故,一旦用户输入用户名/密码,我需要包含出现在 keycloak 登录页面上的用户名/密码验证后的 QR 码,以便在我的登录屏幕上显示第一次登录。那么我们是否有任何 API 可以返回 Keycloak QR 码图像作为响应。

2.)后续登录我将有 OTP 字段,因此需要一个 REST api 来传递 OTP 以及用户名/密码。

如果 keycloak 有,请帮助使用 REST API。通过 Javascript 集成。

与此处用例 1 中描述的类似流程

只想把keycloak当做数据库,为我做所有的操作,输入就是我的屏幕。我确实希望在登录时重定向 URL,但应该独立部署。

标签: loginkeycloakuser-registrationkeycloak-servicesmulti-factor-authentication

解决方案


我已经设法通过 Keycloak 的其余 API 实现了这一点。要实现这一点,您需要自己使用 SPI 扩展 Keycloak。为此,请创建您自己的 Java 项目并扩展org.keycloak.services.resource.RealmResourceProviderorg.keycloak.services.resource.RealmResourceProviderFactory. 您可以在官方文档 ( https://www.keycloak.org/docs/latest/server_development/#_extensions)、github示例和其他堆栈溢出帖子中找到如何执行此操作的更多信息。

一旦你启动并运行它,你可以像这样实现它:

@GET
@Path("your-end-point-to-fetch-the-qr")
@Produces({MediaType.APPLICATION_JSON})
public YourDtoWithSecretAndQr get2FASetup(@PathParam("username") final String username) {
    final RealmModel realm = this.session.getContext().getRealm();
    final UserModel user = this.session.users().getUserByUsername(username, realm);
    final String totpSecret = HmacOTP.generateSecret(20);
    final String totpSecretQrCode = TotpUtils.qrCode(totpSecret, realm, user);
    return new YourDtoWithSecretAndQr(totpSecret, totpSecretQrCode);
}

@POST
@Path("your-end-point-to-setup-2fa")
@Consumes("application/json")
public void setup2FA(@PathParam("username") final String username, final YourDtoWithData dto) {
    final RealmModel realm = this.session.getContext().getRealm();
    final UserModel user = this.session.users().getUserByUsername(username, realm);
    final OTPCredentialModel otpCredentialModel = OTPCredentialModel.createFromPolicy(realm, dto.getSecret(), dto.getDeviceName());
    CredentialHelper.createOTPCredential(this.session, realm, user, dto.getInitialCode(), otpCredentialModel);
}

通过 GET 接收到的秘密必须通过 POST 发回。初始代码是来自您的 2FA 应用程序(例如 Google Authenticator)的代码。二维码是一个字符串,可以img用 src显示'data:image/png;base64,' + qrCodeString;


推荐阅读