The ProviderManager
implementation of Authentication iterates through all the Authentication providers while authenticating and checks whether the specific provider supports the specific token; if yes, then it delegates the request to that provider.
So what we can do is create two subclasses of the UsernamePasswordAuthentication
token for each Entity (in the example, for the seller and the customer). And also subclass the DaoAuthenticationProvider
for the seller and the customer, and each provider would support the token of their respective entity. We would simply delegate the request to the superclass for authenticating since the tokens are subclasses of UsernamePasswordAuthentication
.
On logging in as the seller, we can create the SellerAuthenticationToken
, and for the customer we can create a token for CustomerAuthenticationToken
, and while authenticating the ProviderManager
would delegate it to the correct provider.
Also, you need to implement two UserDetailsService
and set the userdetails correctly for the providers.
All of the configurations and sample code is given below.
@Configuration
public class SecurityConfig{
@Bean
public CustomerAuthenticationProvider customerAuthenticationProvider(@Qualifier("customerUserDetailsService")
UserDetailsService userDetailsService){
CustomerAuthenticationProvider customerAuthenticationProvider = new CustomerAuthenticationProvider();
customerAuthenticationProvider.setPasswordEncoder(passwordEncoder());
customerAuthenticationProvider.setUserDetailsService(userDetailsService);
return customerAuthenticationProvider;
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public SellerAuthenticationProvider sellerAuthenticationProvider(@Qualifier("sellerUserDetailsService")
UserDetailsService userDetailsService
){
SellerAuthenticationProvider sellerAuthenticationProvider = new SellerAuthenticationProvider();
sellerAuthenticationProvider.setPasswordEncoder(passwordEncoder());
sellerAuthenticationProvider.setUserDetailsService(userDetailsService);
return sellerAuthenticationProvider;
}
@Bean
public AuthenticationManager authenticationManager(SellerAuthenticationProvider sellerAuthenticationProvider,
CustomerAuthenticationProvider customerAuthenticationProvider){
return new ProviderManager(sellerAuthenticationProvider, customerAuthenticationProvider);
}
}
public class SellerAuthenticationToken extends UsernamePasswordAuthenticationToken {
public SellerAuthenticationToken(Object principal, Object credentials) {
super(principal, credentials);
}
public SellerAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
super(principal, credentials, authorities);
}
}
public class CustomerAuthenticationToken extends UsernamePasswordAuthenticationToken {
public CustomerAuthenticationToken(Object principal, Object credentials) {
super(principal, credentials);
}
public CustomerAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
super(principal, credentials, authorities);
}
}
public class CustomerAuthenticationProvider extends DaoAuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if(!(authentication instanceof CustomerAuthenticationToken)){
throw new IllegalArgumentException("invalid");
}
return super.authenticate(authentication);
}
@Override
public boolean supports(Class<?> authentication) {
return (CustomerAuthenticationToken.class.isAssignableFrom(authentication));
}
}
public class SellerAuthenticationProvider extends DaoAuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException{
if(!(authentication instanceof SellerAuthenticationToken)){
throw new IllegalArgumentException("invalid");
}
return super.authenticate(authentication);
}
@Override
public boolean supports(Class<?> authentication) {
return (SellerAuthenticationToken.class.isAssignableFrom(authentication));
}
}
//While logging in from the seller login endpoint
Authentication authentication = authenticationManager.authenticate(
new SellerAuthenticationToken(request.username(), request.password())
);
//While logging the customer from the customer endpoint
Authentication authentication = authenticationManager.authenticate(
new CustomerAuthenticationToken(request.username(), request.password())
);