We have a entitlements database which has application id, roles and users mapped to roles per application. Following the advice on thread how do I map user roles to oauth2
I was struggling with same issue, since by default the securityContext has client details I extended the DefaultOauth2RequestFactory and have set the User authentication manually in SecurityContext
public TokenRequest createTokenRequest(Map<String, String> requestParameters, ClientDetails authenticatedClient) {
SecurityContextHolder.getContext()
.setAuthentication(new UsernamePasswordAuthenticationToken(requestParameters.get("username"), null,
userDetailsService.loadUserByUsername(requestParameters.get("username")).getAuthorities()));
return super.createTokenRequest(requestParameters, authenticatedClient);
}
With this code in place the SecurityContext will always be populated by User authentication rather than Client authentication you can do this for specific grant type aswell
if (requestParameters.get("grant_type").equals("password")) { //same code as above }
I ran into the same problem and I also noticed the code was running the checkUserScopes
method twice. I found out that what is missing is that both the user AND the CLIENT need to have the authorities that you want to return.
So define your client in a way like this (adjust roles to your own):
@Bean
public ClientDetailsService clientDetailsService() {
Map<String, ClientDetails> clientDetailsStore = new HashMap<>();
Collection<String> scope = new HashSet<>();
scope.add("user");
scope.add("admin");
Collection<GrantedAuthority> authorities = new HashSet<>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
Collection<String> authorizedGrantTypes = new HashSet<>();
authorizedGrantTypes.add("authorization_code");
BaseClientDetails clientDetails = new BaseClientDetails();
clientDetails.setClientId("clientid");
clientDetails.setClientSecret("{noop}secret"); //noop for Spring Security 5
clientDetails.setScope(scope);
clientDetails.setAuthorities(authorities);
clientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);
clientDetailsStore.put("clientid", clientDetails);
InMemoryClientDetailsService clientDetailsService = new InMemoryClientDetailsService();
clientDetailsService.setClientDetailsStore(clientDetailsStore);
return clientDetailsService;
}
Now the client has the required authorities user and admin.
And configure your request factory:
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
DefaultOAuth2RequestFactory defaultOAuth2RequestFactory = new DefaultOAuth2RequestFactory(clientDetailsService());
defaultOAuth2RequestFactory.setCheckUserScopes(true);
endpoints.requestFactory(defaultOAuth2RequestFactory);
}