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

如何在Keycloak中创建自定义Grant Type?求详细分步指导

Keycloak自定义Grant Type完整实现指南

1. 编写自定义Grant Type类

Keycloak通过SPI(Service Provider Interface)扩展Grant Type,需实现核心处理类和工厂类。

1.1 实现Grant Handler

继承AbstractOAuth2GrantHandler,重写核心方法实现自定义认证逻辑:

package com.example.keycloak.grant;

import org.keycloak.OAuth2Constants;
import org.keycloak.common.ClientConnection;
import org.keycloak.events.EventBuilder;
import org.keycloak.grant.AbstractOAuth2GrantHandler;
import org.keycloak.models.*;
import org.keycloak.protocol.oidc.TokenManager;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.services.managers.ClientSessionCode;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.Map;

public class CustomGrantHandler extends AbstractOAuth2GrantHandler {

    public static final String GRANT_TYPE = "custom_grant";

    @Override
    public Response createAccessTokenResponse(UriInfo uriInfo, ClientConnection clientConnection, RealmModel realm, ClientModel client, UserModel user, AuthenticatedClientSessionModel clientSession, EventBuilder event, TokenManager tokenManager, ClientSessionCode<AuthenticatedClientSessionModel> clientSessionCode, Map<String, String> params) {
        // 1. 校验自定义参数(根据你的序列图业务逻辑调整)
        String customCredential = params.get("custom_credential");
        if (customCredential == null || !validateCustomCredential(customCredential, user)) {
            return Response.status(Response.Status.BAD_REQUEST).entity("Invalid custom credential").build();
        }

        // 2. 复用Keycloak内置逻辑生成AccessToken
        AccessTokenResponse response = tokenManager.responseBuilder(realm, client, user, clientSession, uriInfo, clientConnection)
                .accessToken(true)
                .build();

        // 3. 记录认证事件(可选)
        event.event(org.keycloak.events.EventType.LOGIN)
                .client(client)
                .user(user)
                .detail(OAuth2Constants.GRANT_TYPE, GRANT_TYPE)
                .success();

        return Response.ok(response).build();
    }

    // 自定义凭证校验逻辑,替换为你的业务规则
    private boolean validateCustomCredential(String credential, UserModel user) {
        String storedCredential = user.getFirstAttribute("custom_credential");
        return credential.equals(storedCredential);
    }

    @Override
    public String getGrantType() {
        return GRANT_TYPE;
    }
}

1.2 实现Provider Factory

Keycloak通过工厂类加载自定义Grant Type:

package com.example.keycloak.grant;

import org.keycloak.Config;
import org.keycloak.grant.GrantTypeProvider;
import org.keycloak.grant.GrantTypeProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;

public class CustomGrantHandlerFactory implements GrantTypeProviderFactory {

    @Override
    public GrantTypeProvider create(KeycloakSession session) {
        return new CustomGrantHandler();
    }

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

    @Override
    public void postInit(KeycloakSessionFactory factory) {}

    @Override
    public void close() {}

    @Override
    public String getId() {
        return CustomGrantHandler.GRANT_TYPE;
    }
}

2. 注册自定义Grant Type到Keycloak

2.1 打包扩展JAR

  • 确保项目依赖的Keycloak API版本与部署的Keycloak版本完全一致
  • 在src/main/resources/META-INF/services/下创建文件org.keycloak.grant.GrantTypeProviderFactory,内容为工厂类全路径:
    com.example.keycloak.grant.CustomGrantHandlerFactory
    
  • 打包为JAR文件(如custom-grant-type.jar)

2.2 部署到Keycloak

  1. 将JAR复制到Keycloak安装目录的providers/文件夹
  2. 执行构建脚本更新SPI:
    # Linux/macOS
    ./kc.sh build
    
    # Windows
    kc.bat build
    
  3. 重启Keycloak服务

3. 配置客户端与Realm参数

3.1 启用自定义Grant Type

  1. 登录Keycloak管理控制台,进入目标Realm
  2. 进入Clients,选择目标客户端
  3. 切换到Capability config标签页
  4. 在Authentication flow的Grant types列表中,勾选custom_grant
  5. 点击Save保存配置

3.2 配置业务相关参数(可选)

如果自定义Grant需要用户属性支持(如示例中的custom_credential):

  1. 进入Users,选择目标用户
  2. 切换到Attributes标签页,添加对应属性并设置值
  3. 点击Save

4. 测试自定义Grant Type

4.1 发送Token请求

用curl调用Token端点:

curl -X POST \
  http://localhost:8080/realms/your-realm/protocol/openid-connect/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=custom_grant' \
  -d 'client_id=your-client-id' \
  -d 'client_secret=your-client-secret' \
  -d 'custom_credential=your-test-credential'

4.2 验证响应

  • 成功响应会返回标准的OAuth2 Token结构,包含access_token、refresh_token等字段
  • 用JWT解析工具校验access_token,确认包含预期的用户信息和业务Claim

4.3 异常场景测试

  • 缺少自定义参数:应返回400错误
  • 无效自定义凭证:应返回400错误
  • 未启用该Grant Type的客户端请求:应返回400错误(提示不支持该授权类型)

配置技巧与参考

  • 版本兼容性:务必保证扩展依赖的Keycloak API版本与部署版本一致,避免类加载异常
  • 调试方法:启动Keycloak时添加--debug参数,通过IDE远程调试;或使用org.jboss.logging.Logger打印日志
  • 官方文档:参考Keycloak官方SPI文档中「Grant Type Provider」章节

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 00:50:21