给OAuth2LoginAuthenticationToken添加access_token权限可以吗?

Is it ok to add access_token authorities to the OAuth2LoginAuthenticationToken?

我有一个简单的 spring 引导应用程序,其中包含两项服务 - uiresource。 我正在尝试使用 uaa 服务器配置 oauth2+oidc 身份验证。

当我登录 ui 服务时,spring 安全性使用 id_token 创建身份验证结果(在 OidcAuthorizationCodeAuthenticationProvider 中)并且它不包含除 openid 之外的任何范围.创建身份验证结果时,它只包含一个权限 - ROLE_USER 因此不能在客户端使用权限。

是否可以覆盖 OidcUserService 并从 access_token 添加到用户权限范围以检查客户端的访问权限?

    @Override
    public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
        OidcUser user = super.loadUser(userRequest);
        Collection<? extends GrantedAuthority> authorities = buildAuthorities(
                user,
                userRequest.getAccessToken().getScopes()
        );
        return new DefaultOidcUser(
                authorities,
                userRequest.getIdToken(),
                user.getUserInfo()
        );
    }

安全配置:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .mvcMatchers("/protected/**").hasAuthority("SCOPE_protected")
                .anyRequest().authenticated()
                .and()
            .oauth2Login()
                .userInfoEndpoint().oidcUserService(oidcUserService())
                .and()
            ...

可行,但我不确定这是个好主意。

这是Spring Security documentation中概述的方法,所以方法很好。 唯一的问题是当我实现它时,我没有将所有范围添加到权限集中 - 我提取了具有角色信息的特定声明 - 我在身份中配置的自定义 groups 声明提供商的授权服务器。

我提供了一些示例代码,说明如何使用 Spring Webflux 执行此操作,因为大多数示例显示了如何根据您的代码使用 Spring MVC 执行此操作。

注意:我对使用 reactor 非常缺乏经验!

public class CustomClaimsOidcReactiveOAuth2UserService implements ReactiveOAuth2UserService<OidcUserRequest, OidcUser> {

    private final OidcReactiveOAuth2UserService service = new OidcReactiveOAuth2UserService();

    public Mono<OidcUser> loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
        log.debug("inside CustomClaimsOidcReactiveOAuth2UserService..");

        Mono<OidcUser> mOidcUser = service.loadUser(userRequest);

        return mOidcUser
                .log()
                .cast(DefaultOidcUser.class)
                .map(DefaultOidcUser::getClaims)
                .flatMapIterable(Map::entrySet)
                .filter(entry -> entry.getKey().equals("groups"))
                .flatMapIterable(roleEntry -> (JSONArray) roleEntry.getValue())
                .map(roleString -> {
                    log.debug("roleString={}", roleString);
                    return new OidcUserAuthority((String) roleString, userRequest.getIdToken(), null);
                })
                .collect(Collectors.toSet())
                .map(authorities -> {
                    log.debug("authorities={}", authorities);
                    return new DefaultOidcUser(authorities, userRequest.getIdToken());
                });
    }
}
...
@Bean
ReactiveOAuth2UserService<OidcUserRequest, OidcUser> userService() {
    return new CustomClaimsOidcReactiveOAuth2UserService();
}