Reputation: 357
We're developing Spring 4 REST/JSON API but we need to have custom Authentication service to authenticate against 3rd party service.
restrictions: We don't want to ask the user for username/password. we are authenticating using "cookie" (send with the request initiator). And we need this authentication process in background. (Might sound weird but that's the case).
we could implement that using registering custom authentication/authorization request filters. but that made us loosing the power of spring "authorization" module that we are planning to use afterwards.
So what we did till now, wrote custom WebSecurityConfigurerAdapter with our own custom AuthenticationProvider and UserDetailsService but these configuration doesn't seem to work.
the application doesn't go inside AuthenticationProvider.authenticate
here is the configuration we had.
AuthenticationProvider.java:
@Service
public class AuthenticationService implements AuthenticationProvider, UserDetailsService {
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
// DOESN'T ENTER THIS FUNCTION
// do authentication stuff
}
@Override
public boolean supports(Class<?> authentication) {
// JUST FOR TESTING
return true;
}
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
// DOESN'T ENTER THIS METHOD
return null;
}
}
SecurityConfig.java:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfig.class);
@Autowired
private AuthenticationService authService;
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/ignoredURL/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() //HTTP with Disable CSRF
.authorizeRequests()
.antMatchers("/api/XYZ/**").hasRole("ADMIN")
.anyRequest().authenticated();
// adding ".httpBasic()" automatically prompts user for username/password
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// THIS IS NOT TYPO, I use one service implements both interfaces.
auth.userDetailsService(authService);
auth.authenticationProvider(authService);
}
}
Upvotes: 2
Views: 2404
Reputation: 357
Fixed by adding 2 more classes (Filter extending AbstractPreAuthenticatedProcessingFilter
and another class CustomUser
implements UserDetails
) then made my AuthenticaitonService
implements spring UserDetailsService
here are the details:
please have a look on what this filter does and how it works
1- Create AbcFilter
extends spring AbstractPreAuthenticatedProcessingFilter
2- Override "getPreAuthenticatedPrincipal". This method extracted the cookie
value and return it. (Whatever the Object you return here is what you get as a parameter in UserDetailsService.loadUserByUsername
).
3- Modified my service to implement spring UserDetailsService
and inside loadUserByUsername
did all authentication logic here and set all logged in user in CustomUser
object. Then return it.
4- Whenever request matches /api/XYZ/**
, Spring will call your CustomUser.getAuthorities
and try to find ADMIN
role there.
Upvotes: 1