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

如何为Keycloak Token端点添加自定义请求/响应头?

给Keycloak Token端点添加自定义请求头的实现方案

当然可以实现,核心思路是通过自定义Authenticator SPI拦截Token端点的请求,获取自定义请求头并传递给你的User Federation逻辑,具体步骤如下:

1. 实现自定义Authenticator

创建一个Authenticator,用来拦截Direct Grant(密码授权)流程的请求,提取自定义请求头并存储到认证上下文里,方便后续User Federation调用:

public class CustomHeaderAuthenticator implements Authenticator {

    @Override
    public void authenticate(AuthenticationContext context) {
        // 获取HTTP请求对象
        HttpRequest request = context.getHttpRequest();
        // 提取自定义请求头,这里以X-Custom-Header为例
        String customHeaderValue = request.getHttpHeaders().getFirst("X-Custom-Header");
        
        // 将头信息存入认证上下文,供后续User Federation使用
        if (customHeaderValue != null) {
            context.getAuthenticationSession().setAttribute("CUSTOM_HEADER", customHeaderValue);
        }
        
        // 直接通过,不阻断流程
        context.success();
    }

    // 实现其他必须的方法(返回默认值即可)
    @Override
    public void action(AuthenticationContext context) {}

    @Override
    public boolean requiresUser() {
        return false;
    }

    @Override
    public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
        return true;
    }

    @Override
    public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {}

    @Override
    public void close() {}
}

同时需要实现对应的Factory类,用来注册这个Authenticator:

public class CustomHeaderAuthenticatorFactory implements AuthenticatorFactory {

    public static final String ID = "custom-header-authenticator";

    @Override
    public String getId() {
        return ID;
    }

    @Override
    public String getReferenceCategory() {
        return "direct-grant";
    }

    @Override
    public boolean isConfigurable() {
        return false;
    }

    @Override
    public Authenticator create(KeycloakSession session) {
        return new CustomHeaderAuthenticator();
    }

    // 实现其他必须的方法,设置显示名称和描述
    @Override
    public String getDisplayType() {
        return "自定义请求头提取器";
    }

    @Override
    public String getHelpText() {
        return "从Token请求中提取自定义头并存储到认证会话";
    }

    @Override
    public List<ProviderConfigProperty> getConfigProperties() {
        return Collections.emptyList();
    }

    @Override
    public boolean isUserSetupAllowed() {
        return false;
    }

    @Override
    public void init(Config.Scope config) {}

    @Override
    public void postInit(KeycloakSessionFactory factory) {}

    @Override
    public void close() {}
}

最后在项目的META-INF/services/org.keycloak.authentication.AuthenticatorFactory文件里注册这个Factory:

com.yourpackage.CustomHeaderAuthenticatorFactory

2. 配置Keycloak认证流程

把自定义Authenticator加到Direct Grant流程里:

  • 进入Keycloak后台,打开目标Realm的Authentication -> Flows
  • 找到Direct Grant流程,点击右侧的Copy,创建一个自定义流程(比如命名为Custom Direct Grant)
  • 展开Custom Direct Grant下的Direct Grant Validate Username,点击Add execution
  • 选择你创建的自定义请求头提取器,设置为REQUIRED后保存
  • 切换到Bindings标签,把Direct Grant Flow切换为你刚创建的Custom Direct Grant

3. 在User Federation中获取自定义请求头

在你已实现的CredentialInputValidator的validateCredential方法里,从认证会话中取出之前存储的头信息,结合凭证做自定义验证:

@Override
public boolean validateCredential(KeycloakSession session, RealmModel realm, UserModel user, CredentialInput input) {
    if (!input.getType().equals(UserCredentialModel.PASSWORD)) {
        return false;
    }
    
    // 从认证会话获取自定义头
    AuthenticationSessionModel authSession = session.getContext().getAuthenticationSession();
    String customHeaderValue = (String) authSession.getAttribute("CUSTOM_HEADER");
    
    // 调用你的自定义验证逻辑,传入用户名、密码和自定义头信息
    String password = input.getChallengeResponse();
    return yourCustomValidationLogic(user.getUsername(), password, customHeaderValue);
}

测试请求

现在你可以在Token请求中添加自定义头,示例如下:

curl --location --request POST 'https://localhost:8081/auth/realms/global/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'X-Custom-Header: my-custom-value' \
--data-urlencode 'client_id=login' \
--data-urlencode 'username=balabla@bla.com' \
--data-urlencode 'password=balbabsfeds@123'

注意事项

  • 打包SPI时要确保jar包含所有必要依赖,部署到Keycloak的standalone/deployments(传统模式)或providers(Quarkus模式)目录
  • 不同Keycloak版本的SPI接口可能略有差异,需对应版本调整代码
  • 如果需要对自定义头做合法性校验(比如必须存在、格式符合要求),可以在Authenticator的authenticate方法里添加逻辑,不通过则抛出错误终止流程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 18:24:54