I have a spring boot application secured using a simple form based login. There is a necessity to add an API key support. I have created datasource to store the key and link it with user account. I am not sure that I am adding the filter part for API key authentication correctly.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication().withUser("test")
.password(passwordEncoder.encode("test")).roles("USER","ADMIN");
}
@Override
public void configure(HttpSecurity httpSecurity) throws Exception {
TokenAuthenticationFilter tokenAuthenticationFilter = new TokenAuthenticationFilter(authHeaderName);
tokenAuthenticationFilter.setAuthenticationManager(authentication -> {
String principal = (String) authentication.getPrincipal();
Optional<AuthToken> authTokenOptional = authTokenRepo.findByAuthKey(principal);
if (!authTokenOptional.isPresent())
{
throw new BadCredentialsException("The API key was not found "
+ "or not the expected value.");
}
authentication.setAuthenticated(true);
return authentication;
});
httpSecurity.authorizeRequests()
.antMatchers("/login", "/userlogin/**")
.permitAll()
.antMatchers("/**")
.hasAnyRole("ADMIN", "USER")
.and()
.formLogin()
.successForwardUrl("/userlogin/success")
.failureForwardUrl("/userlogin/failure")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.permitAll()
.and()
.addFilterBefore(tokenAuthenticationFilter, AnonymousAuthenticationFilter.class)
.csrf()
.disable();
}
}
public class TokenAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
private final String authHeaderName;
public TokenAuthenticationFilter(String authHeaderName){
this.authHeaderName = authHeaderName;
}
@Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
return request.getHeader(authHeaderName);
}
@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
return "Not available";
}
}
I am not sure if I'm adding the Filter in the correct order. I know I can create MultiHttpSecurityConfig, however unlike in MultiHttpSecurityConfig, would like to use same endpoints. I would like Spring Security to first try the API key, if not present use the form login.