I am trying to authenticate a user from facebook and store it's username and provide custom permission to subset of users who will be admin for my application. My question is, How do I provide custom roles like "Admin" to the authenticated and authorize it in Oauth2Client.
@Configuration
class WebSecurityConfiguration extends GlobalAuthenticationConfigurerAdapter {
@Autowired
UserRepository userRepository;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService());
}
@Bean
UserDetailsService userDetailsService() {
return new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User account = userRepository.findOne(username);
if (account != null) {
List<String> rolesList = userRepository.getRoles(username);
String[] roles = new String[rolesList.size()];
// userRepository.findRoles List<String> roles =
//account.getUserroles().;
User user = new User(account.getUserssoid(), account.getSecretKey(), true, true, true, true,
AuthorityUtils.createAuthorityList(rolesList.toArray(roles)));
return user;
} else {
throw new UsernameNotFoundException("could not find the user '" + username + "'");
}
}
};
}
}
I want to do similar thing using OAuth2 Client.
Thanks
What you need is custom UserInfoTokenServices Implementation with your ersistence repository as argument and then in your facebook filter use the custom UserInfoTokenServices insted of defaul like this:
private Filter ssoFilter() {
CompositeFilter filter = new CompositeFilter();
List<Filter> filters = new ArrayList<>();
filters.add(ssoFilter(facebook(), "/login/facebook"));
filters.add(ssoFilter(google(), "/login/google"));
filter.setFilters(filters);
return filter;
}
private Filter ssoFilter(ClientResources client, String path) {
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(path);
OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
filter.setRestTemplate(template);
CustomSocialUserInfoTokenServices tokenServices = new CustomSocialUserInfoTokenServices(
client.getResource().getUserInfoUri(), client.getClient().getClientId(), userRepository);
tokenServices.setRestTemplate(template);
filter.setTokenServices(tokenServices);
return filter;
}
Than is your custom UserInfoTokenServices you can add your custom AuthoritiesExtractor like this
private AuthoritiesExtractor authoritiesExtractor = new CustomSocialAuthoritiesExtractor();
There you can run your DB query or any logic to fetch your custom Authority and pass on to your clients.
Hope this helps
You dont neccessaraly need a CustomSocialUserInfoTokenServices.
Instead u could use existing UserInfoTokenServices and set your CustomSocialAuthoritiesExtractor.
private Filter ssoFilter(ClientResources client, String path) {
...
UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(), client.getClient().getClientId());
tokenServices.setRestTemplate(template);
tokenServices.setAuthoritiesExtractor(new CustomSocialAuthoritiesExtractor());
filter.setTokenServices(tokenServices);
return filter;
}
public class CustomSocialAuthoritiesExtractor implements AuthoritiesExtractor {
@Override
public List<GrantedAuthority> extractAuthorities(Map<String, Object> map) {
String authorities = "ROLE_CUSTOMUSER";
return AuthorityUtils.commaSeparatedStringToAuthorityList(authorities);
}
}
You can do it even simpler when you don't want to provide your own UserInfoTokenServices. Just provide an AuthoritiesExtractor bean in your security config.
@Bean
public AuthoritiesExtractor customAuthoritiesExtractor() {
return new CustomAuthoritiesExtractor();
}
public class CustomAuthoritiesExtractor implements AuthoritiesExtractor {
@Override
public List<GrantedAuthority> extractAuthorities(Map<String, Object> map) {
// map contains information from your OAuth profile provider
boolean userExist = true; // TODO
if (!userExist) {
throw new BadCredentialsException("User does not exists");
}
String authorities = "ROLE_ADMIN"; // TODO your own roles
return AuthorityUtils.commaSeparatedStringToAuthorityList(authorities);
}
}
For more details refer to this tutorial: https://spring.io/guides/tutorials/spring-boot-oauth2/#_social_login_logout