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

Spring Authorization Server:如何为各授权类型配置不同Scope?

问题

我想要自定义授权类型mfa,流程如下:用户需先获取带有mfa_required scope的访问令牌,再使用该令牌通过mfa授权类型获取另一访问令牌,后者具备write、read等可访问资源服务器的scope。

当前实现需要创建两个RegisteredClient:
第一个用于获取带mfa_required的令牌:

RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
        .clientId("cheems_doge")
        .clientSecret("very_secret_wow")
        .clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
        .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
        .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
        .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
        .redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
        .scope("mfa_required") // 该令牌仅可用于mfa授权类型
        .clientSettings(
                ClientSettings.builder() // 移除同意页
                .requireAuthorizationConsent(false)
                .requireProofKey(true)
                .build())
        .build();

第二个用于通过mfa授权类型获取资源访问令牌:

RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
                .clientId("cheems_doge_2")
                .clientSecret("very_secret_wow_2")
                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT)
                .authorizationGrantType(CustomGrantType.MFA)
                .redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
                .scope("write read etc..") // 该令牌可访问资源服务器
                .clientSettings(
                        ClientSettings.builder()
                                .requireAuthorizationConsent(true)
                                .requireProofKey(false)
                                .build())
        .build();

但目前无法在单个RegisteredClient中为不同授权类型配置不同Scope,只能创建两个RegisteredClient,导致客户端需存储两个client_id。请问是否存在为每种授权类型单独配置Scope的方法?

解决方案

Spring Security OAuth2默认的RegisteredClient模型不支持直接为每个授权类型绑定专属Scope,但可以通过以下两种方式实现类似效果,避免维护多个客户端:

1. 自定义令牌颁发逻辑

在授权服务器的令牌端点处理器中,根据当前使用的授权类型动态过滤可颁发的Scope:

  • 先在单个RegisteredClient中配置所有需要的Scope(mfa_required、write、read等)
  • 自定义OAuth2TokenCustomizer或者扩展AuthorizationTokenServices,在颁发令牌时做如下处理:
    • 若当前授权类型是authorization_code/client_credentials,仅保留mfa_required Scope
    • 若当前授权类型是自定义的mfa,仅保留write、read等资源访问Scope

示例代码片段:

@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> jwtTokenCustomizer() {
    return context -> {
        AuthorizationGrantType grantType = context.getAuthorizationGrantType();
        Set<String> allowedScopes = new HashSet<>();
        
        if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(grantType) 
            || AuthorizationGrantType.CLIENT_CREDENTIALS.equals(grantType)) {
            allowedScopes.add("mfa_required");
        } else if (CustomGrantType.MFA.equals(grantType)) {
            allowedScopes.addAll(Set.of("write", "read"));
        }
        
        context.getClaims().claim("scope", String.join(" ", allowedScopes));
        // 更新令牌的scope集合
        context.getTokenContext().setScopes(allowedScopes);
    };
}

2. 扩展RegisteredClient模型

如果需要更严谨的配置隔离,可以自定义RegisteredClient的存储逻辑:

  • 扩展默认的RegisteredClient实体,添加grantTypeScopes映射字段,存储每个授权类型对应的Scope列表
  • 自定义RegisteredClientRepository或RegisteredClientService,查询客户端时返回包含自定义映射的实例
  • 在授权流程中,从自定义的RegisteredClient中获取当前授权类型对应的有效Scope,替代默认的全局Scope集合

这种方式配置更清晰,但需要修改客户端存储的底层实现,适合对权限控制有严格要求的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 17:15:37