The solution is the implementation of a custom UserInfoTokenServices
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/UserInfoTokenServices.java
Just Provide your custom implementation as a Bean and it will be used instead of the default one.
Inside this UserInfoTokenServices you can build the principal
like you want to.
This UserInfoTokenServices is used to extract the UserDetails out of the response of the /users
endpoint of your authorization server. As you can see in
private Object getPrincipal(Map<String, Object> map) {
for (String key : PRINCIPAL_KEYS) {
if (map.containsKey(key)) {
return map.get(key);
}
}
return "unknown";
}
Only the properties specified in PRINCIPAL_KEYS
are extracted by default. And thats exactly your problem. You have to extract more than just the username or whatever your property is named. So look for more keys.
private Object getPrincipal(Map<String, Object> map) {
MyUserDetails myUserDetails = new myUserDetails();
for (String key : PRINCIPAL_KEYS) {
if (map.containsKey(key)) {
myUserDetails.setUserName(map.get(key));
}
}
if( map.containsKey("email") {
myUserDetails.setEmail(map.get("email"));
}
//and so on..
return myUserDetails;
}
Wiring:
@Autowired
private ResourceServerProperties sso;
@Bean
public ResourceServerTokenServices myUserInfoTokenServices() {
return new MyUserInfoTokenServices(sso.getUserInfoUri(), sso.getClientId());
}
!!UPDATE with Spring Boot 1.4 things are getting easier!!
With Spring Boot 1.4.0 a PrincipalExtractor was introduced. This class should be implemented to extract a custom principal (see Spring Boot 1.4 Release Notes).