0

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.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Andrews
  • 895
  • 3
  • 15
  • 30
  • Does this answer your question? [How to provide multiple ways of authentication with Spring Security](https://stackoverflow.com/questions/49225035/how-to-provide-multiple-ways-of-authentication-with-spring-security) – Eleftheria Stein-Kousathana Aug 10 '21 at 07:52
  • That kind of answers my question. However, would like to understand what is wrong with this approach. There it is not `AbstractPreAuthenticatedProcessingFilter`. Some of the steps involved are not the same, however, will confirm by checking other configurations that are applicable here. – Andrews Aug 11 '21 at 05:25

0 Answers0