如何为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
相关产品推荐
相关产品推荐

