javaspringspring-securityspring-bootpre-authentication

Spring Security HeaderPreAuthentication Principal Not Resolved from @AuthenticationPrincipal


I have an existing Spring Boot Application with authentication to the web application handled by a third party authentication service. Like SiteMinder, the 3rd party service injects a header into the HTTP requests, say USER_HEADER. I am tasked with configuring the existing app to extract this HTTP header and make the resulting Auth object available to the MVC layer's controllers via the Spring Security @AuthenticatedPrincipal annotation.

As mentioned, project is a Spring Boot application, version 1.1.9.RELEASE, with Java 8.

(The code shown below is from a test project that mirrors functionality)

Note that this application is Java Config only. No XML is permitted (mandate from my lead)

By digging through the Spring Security reference and various other articles I know that I need to use a RequestHeaderAuthenticationFilter and inject it into the filter chain to grab the username from the request header.

Filter:

public class HeaderAuthenticationFilter extends RequestHeaderAuthenticationFilter {
    private static final Logger logger = LoggerFactory.getLogger(HeaderAuthenticationFilter.class);
    private final String HEADER = "USER_HEADER";

    public HeaderAuthenticationFilter() {
        super();
        this.setPrincipalRequestHeader(HEADER);

        // This setting returns an HTTP 404 with no error message instead of an HTTP 500 with the "missing header" exception message
        this.setExceptionIfHeaderMissing(false);
    }

    @Override
    protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
        logger.debug("Authorizing URI: " + request.getRequestURI());

        try {
            return super.getPreAuthenticatedPrincipal(request);
        } catch(PreAuthenticatedCredentialsNotFoundException e) {
            logger.error("Could not find request header " + HEADER + " in request", e);
            return null;
        }
    }
}

Very basic filter as you can see.

With the code I have now, the user gets extracted from the HTTP request, makes it through the PreAuthentication process where the PreAuthenticatedAuthenticationToken gets created by a custom AuthenticationManager, the User business object is injected into the token as the principal, and the token is finally assigned to the SecurityContext with: SecurityContextHolder.getContext().setAuthentication(principal);

However when I annotate my Controller methods with @AuthenticationPrincipal User user, the User object returned is a null'd User object. When I change the method parameter to Authentication user and explicitly call user.getPrincipal() I get the user object just fine. Is there a reason why @AuthenticationPrincipal is failing like this?

Thanks and please let me know if more details are needed!


Solution

  • The reason that @AuthenticationPrincipal was not resolving is because I did not annotate my WebSecurityConfigurerAdapter class with @EnableWebMvcSecurity

    Adding this annotation solved the issue