Мое решение здесь:
При выполнении метода loadClientByClientId
объект Principal
хранится в SecurityContext
еще не существует, но это происходит, когда
loadUserByUsername
метод выполнен с небольшим наблюдением:
Principal
объект в этой точке содержит client_id
, а не
username
, что приводит к настройке объекта UserDetailsService
вместо ClientsDetailsService
. Затем с реляционной сущностью (JPA)
Я присоединился к client_id
с username
, дающим ожидаемый результат.
Итак, код для UserDetailsService
агрегатов:
@Service
public class UsuarioService implements IUsuarioService, UserDetailsService{
private Logger logger = LoggerFactory.getLogger(UsuarioService.class);
@Autowired
private IUsuarioDao usuarioDao;
@Override
@Transactional(readOnly=true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Usuario usuario = usuarioDao.findByUsername(username);
if( usuario == null ) {
logger.error("Login error: Username not found in storage");
throw new UsernameNotFoundException("Login error: Username not found in storage");
}
List<GrantedAuthority> authorities = usuario.getRoles().stream().map( role -> new SimpleGrantedAuthority( role.getNombre() )).collect(Collectors.toList());
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String applicationID = "";
if (principal instanceof UserDetails) {
applicationID = ((UserDetails)principal).getUsername();
} else {
applicationID = principal.toString();
}
logger.info("Application: {} ", applicationID);
if( applicationID == null || applicationID.isEmpty() ) {
logger.error("Application ID can't be empty");
throw new InsufficientAuthenticationException("Application ID can't be empty");
}
OAuthClientDetails app = findApplicationByUsername( usuario.getClientes(), applicationID);
if( app == null ) {
logger.error("Unauthorized user for application {}", applicationID);
throw new UnapprovedClientAuthenticationException("Unauthorized user for application " + applicationID);
}
return new User(username, usuario.getPassword(), usuario.getEnabled(), true, true, true, authorities);
}
private OAuthClientDetails findApplicationByUsername( final List<OAuthClientDetails> list, final String clientID ){
return list.stream().filter( p -> p.getClientId().equals(clientID) ).findAny().orElse(null); } }
А конфигурация AuthorizationServer:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{
@Autowired DataSource dataSource;
@Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter())
;
}
@Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter jwt = new JwtAccessTokenConverter();
jwt.setSigningKey(JwtConfig.RSA_PRIVATE_KEY);
jwt.setVerifierKey(JwtConfig.RSA_PUBLIC_KEY);
return jwt;
}
}
Очень благодарен за помощь и идеи.