SME
SME

Reputation: 556

Spring Security custom AuthenticationProvider authenticate method called twice

I am developing a Spring Boot that uses an API Key to authenticate. I have created a custom Authentication provider and the authenticate method is called twice. Can anyone tell me why it's being called twice?

This is my authenticate method:

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    ApiAuthenticationToken authenticationToken = (ApiAuthenticationToken) authentication;

    /**
     * Authenticate the token
     */
    ValidateApiKeyRequest request = new ValidateApiKeyRequest(authenticationToken.getApiKey());
    ValidateApiKeyResp resp = getValidateApiKeyCommand().execute(request);

    /**
     * Populate and return a new authenticaiton token
     */
    return createSuccessAuthentication(resp);
}

and this is the createSuccessAuthentication method:

protected Authentication createSuccessAuthentication(final ValidateApiKeyResp resp) {
    List<GrantedAuthority> authorities = Lists.newArrayList();
    authorities.add(new SimpleGrantedAuthority("API_KEY"));
    return new ApiAuthenticationToken(resp.getApiKey(), authorities, true);
}

this is the ApiAuthenticationToken constructor:

public ApiAuthenticationToken(final ApiKey apiKey, Collection<? extends GrantedAuthority> authorities, boolean authenticated) {
    super(authorities);
    setAuthenticated(true);
    this.apiKey = apiKey;
}

This is my security configuration:

protected void configure(HttpSecurity http) throws Exception {
    http.antMatcher(CONFIGURATION_MATCHER)
        .exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint())
        .and()
        .addFilterBefore(apiKeyAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
        .csrf().disable()
        .authorizeRequests().antMatchers(CONFIGURATION_MATCHER).authenticated()
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authenticationProvider(apiKeyAuthenticationProvider());

Upvotes: 1

Views: 1629

Answers (2)

denizg
denizg

Reputation: 952

I had similar error. When I throw custom exception in my custom provider, it tries authentication twice. I change to my custom exception's super class from AuthenticationException to LockedException, it solved. My custom exception is still AuthenticationException, because LockedException is inherited from AuthenticationException.

Upvotes: 0

SME
SME

Reputation: 556

Just in case anyone else has this issue:

The problem was related to my spring security configuration. I had several methods annotated with @Bean - see below

@Bean
public ApiKeyAuthenticationProvider apiKeyAuthenticationProvider() {
    return new ApiKeyAuthenticationProvider(getValidateApiKeyCommand());
}

@Bean
public RestAuthenticationEntryPoint restAuthenticationEntryPoint() {
    return new RestAuthenticationEntryPoint();
}

@Bean
public ApiKeyAuthenticationFilter apiKeyAuthenticationFilter() throws Exception {
    ApiKeyAuthenticationFilter apiKeyAuthenticationFilter = new ApiKeyAuthenticationFilter();
    apiKeyAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
    apiKeyAuthenticationFilter.setAuthenticationSuccessHandler(new ApiKeyAuthenticationSuccessHandler());
    apiKeyAuthenticationFilter.setAuthenticationFailureHandler(new ApiKeyAuthenticationFailureHandler());
    return apiKeyAuthenticationFilter;
}

But theses beans were getting registered again in the configure(HttpSecurity http) method.

protected void configure(HttpSecurity http) throws Exception {

    http.antMatcher(CONFIGURATION_MATCHER)
        .exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint())
        .and()
        .addFilterBefore(apiKeyAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
        .csrf().disable()
        .authorizeRequests().antMatchers(CONFIGURATION_MATCHER).authenticated()
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authenticationProvider(apiKeyAuthenticationProvider());
}

The fix was to remove the @Bean annotation. Seems obvious now :)

Upvotes: 1

Related Questions