给OAuth2LoginAuthenticationToken添加access_token权限可以吗?
Is it ok to add access_token authorities to the OAuth2LoginAuthenticationToken?
我有一个简单的 spring 引导应用程序,其中包含两项服务 - ui
和 resource
。
我正在尝试使用 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();
}
我有一个简单的 spring 引导应用程序,其中包含两项服务 - ui
和 resource
。
我正在尝试使用 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();
}