You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Keycloak在Token请求URL中添加自定义TOTP字段?

实现Keycloak通过Token端点直接传入自定义TOTP获取Token的方案

默认Keycloak的OpenID Connect Token端点(/auth/realms/{realm}/protocol/openid-connect/token)不支持直接传入自定义TOTP参数,需要通过扩展认证SPI并修改认证流程来实现,具体步骤如下:

1. 开发自定义认证SPI

编写自定义Authenticator,用于读取Token请求中的totp参数并执行自定义验证逻辑:

核心代码示例

public class CustomTotpAuthenticator implements Authenticator {

    @Override
    public void authenticate(AuthenticationFlowContext context) {
        // 从Token请求的表单参数中获取totp值
        String totp = context.getHttpRequest().getDecodedFormParameters().getFirst("totp");
        
        if (StringUtils.isBlank(totp)) {
            context.failure(AuthenticationFlowError.INVALID_CREDENTIALS, 
                context.form().setError("totp-missing").createForm("error-page.ftl"));
            return;
        }

        UserModel user = context.getUser();
        // 执行自定义TOTP验证逻辑(比如调用外部验证服务、读取用户存储的密钥验证)
        boolean isTotpValid = validateCustomTotp(user, totp);

        if (isTotpValid) {
            context.success();
        } else {
            context.failure(AuthenticationFlowError.INVALID_CREDENTIALS, 
                context.form().setError("invalid-totp").createForm("error-page.ftl"));
        }
    }

    // 自定义TOTP验证逻辑,根据你的需求实现
    private boolean validateCustomTotp(UserModel user, String totp) {
        // 示例:从用户属性中获取绑定的TOTP密钥,用HMAC算法验证
        String secret = user.getFirstAttribute("custom-totp-secret");
        if (secret == null) return false;
        // 这里替换成你的TOTP验证实现,比如用Google Authenticator的算法
        return TotpUtils.validateTOTP(secret, totp);
    }

    // 实现其他必要的接口方法
    @Override
    public boolean requiresUser() { return true; }
    @Override
    public void action(AuthenticationFlowContext context) {}
    @Override
    public void close() {}
    @Override
    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) { return true; }
    @Override
    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {}
}

同时编写对应的AuthenticatorFactory注册SPI,打包成jar后放入Keycloak的providers目录,执行kc.sh build(Windows用kc.bat build)并重启Keycloak。

2. 修改Realm的Direct Grant认证流程

Token端点的密码授权模式依赖Direct Grant流程,需将自定义TOTP验证步骤加入该流程:

  • 登录Keycloak管理后台,进入目标Realm(gilgamesh)
  • 进入「Authentication」→「Flows」,复制默认的Direct Grant流程(避免修改默认流程)
  • 在复制后的流程中,找到Direct Grant Validator子流程,添加新的执行步骤,选择你开发的自定义TOTP Authenticator
  • 将该步骤的「Requirement」设置为「REQUIRED」,确保在密码验证后执行TOTP验证
  • 进入「Authentication」→「Bindings」,将复制后的流程设置为Realm的默认Direct Grant Flow

3. 测试Token请求

使用POST请求调用Token端点,传入totp参数即可:

curl -X POST "http://localhost:8082/auth/realms/gilgamesh/protocol/openid-connect/token" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "username=test-user" \
     -d "password=test-pass" \
     -d "grant_type=password" \
     -d "client_id=your-client-id" \
     -d "client_secret=your-client-secret" \ # 保密客户端需要传此参数
     -d "totp=123456" # 自定义TOTP值

注意事项

  • 自定义TOTP的密钥可存储在Keycloak用户属性中,或关联外部系统的用户TOTP信息
  • 需根据Keycloak版本调整SPI代码,不同版本的接口可能有差异
  • 错误处理可根据需求自定义错误页面或返回JSON错误信息

内容的提问来源于stack exchange,提问作者LordArnur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:55:06