Home > Software design >  AuthenticationManager.authenticate method not getting called
AuthenticationManager.authenticate method not getting called

Time:03-19

I am trying to follow the API Key authentication code from this answer: https://stackoverflow.com/a/48448901

I created my filter class:

package com.propfinancing.CADData.web;

import javax.servlet.http.HttpServletRequest;
import org.slf4j.LoggerFactory;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;

public class PullAPIKeyFromHeaderFilter extends AbstractPreAuthenticatedProcessingFilter {
  private String apiKeyHeaderName;
  
  public PullAPIKeyFromHeaderFilter(String apiKeyHeaderName) {
    this.apiKeyHeaderName = apiKeyHeaderName;
  }
  
  @Override
  protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
    String headerValue = request.getHeader(apiKeyHeaderName);
    return request.getHeader(headerValue);
  }

  @Override
  protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
    return apiKeyHeaderName;
  }
}

And then I implemented my security configuration:

package com.propfinancing.CADData.web;

import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

@Configuration
@EnableWebSecurity
@Order(1)
public class APIKeySecurityConfig extends WebSecurityConfigurerAdapter {
  @Value("${caddata.apiKey.header.name}")
  private String apiKeyHeaderName;

  @Value("${caddata.apiKey}")
  private String apiKey;

  @Override
  protected void configure(HttpSecurity httpSecurity) throws Exception {
    PullAPIKeyFromHeaderFilter pullAPIKeyFromHeaderfilter = new PullAPIKeyFromHeaderFilter(apiKeyHeaderName);
    
    AuthenticationManager authManager = new AuthenticationManager() {
      @Override
      public Authentication authenticate(Authentication authentication) 
      throws AuthenticationException {
        String principal = (String) authentication.getPrincipal();
        if (!apiKey.equals(principal))
          throw new BadCredentialsException("Invalid API key");
        authentication.setAuthenticated(true);
        return authentication;
      }
    };
    pullAPIKeyFromHeaderfilter.setAuthenticationManager(authManager);
    
    httpSecurity.antMatcher("/**");
    httpSecurity.addFilter(pullAPIKeyFromHeaderfilter);
    httpSecurity.requiresChannel().anyRequest().requiresSecure();
    httpSecurity.csrf().disable();
    httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry urlAuthConfigurer = httpSecurity.authorizeRequests();
    ExpressionUrlAuthorizationConfigurer<HttpSecurity>.AuthorizedUrl authorizedUrl = urlAuthConfigurer.anyRequest();
    authorizedUrl.authenticated();
  }
}

When I do an external call to the application with the header as part of the request, I get a 403 Forbidden response. I can see the filter pulling the key from the header. That part is working.

But, the authenticate() method is not being called to check if the header is valid. I am not sure what I missed, the code looks the same to me.

Any ideas?

CodePudding user response:

Looks like the wrong base class, per https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.html :

The purpose is then only to extract the necessary information on the principal from the incoming request, rather than to authenticate them.

Try extending https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.html instead.

CodePudding user response:

I was not able to get the code above to work, but I changed it to use the second answer on that thread https://stackoverflow.com/a/63852212 which worked as expected.

  • Related