Spring SecurityContext returning null authentication on error pages

14,325

Solution 1

The problem you're running into is that the ExceptionTranslationFilter which translates exceptions into error pages comes before the SecurityContextPersistenceFilter which pulls the authentication out of the SecurityContextRepository and puts it into the SecurityContextHolder. When the request finishes the SecurityContextPersistenceFilter takes the information back out of the SecurityContextHolder.

The reason it clears the SecurityContextHolder is that the SecurityContextHolder is typically thread local and if the servlet container were to reuse a thread (most do this) they might accidentally give those credentials to someone else.

Typically the ExceptionTranslationFilter is the outermost filter to avoid the risk of any exceptions not getting translated.

Your best bet is to probably write a custom ExceptionTranslationFilter which takes in the SecurityContextRepository (often the HTTP session as you mentioned) and provides access to the Authentication via the SecurityContextRepository and not the SecurityContextHolder. Keep in mind that the Authentication will still be null if the user isn't logged in.

Solution 2

The problem may be that springSecurityFilterChain is not intercepting ERRORS. Try changing your mapping in web.xml to be

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>
Share:
14,325
Infeligo
Author by

Infeligo

Updated on June 08, 2022

Comments

  • Infeligo
    Infeligo almost 2 years

    I am trying to write a custom error page for errors like 403 (access denied) and 500 (internal server error). They would be rendered from Velocity template and have all messages translated using user's locale. Authentication and locale resolution works fine in the application.

    I set up location in web.xml to be the desired page and in webmvc-context.xml I added requet-to-view controller via .

    The problem I ran into is that SecurityContextHolder.getContext().getAuthentication() returns null in the error page view. Looking at the log I saw:

    06.10 14:42:26 DEBUG - context.HttpSessionSecurityContextRepository(HttpSessionSecurityContextRepository.java:351) -  - SecurityContext stored to HttpSession: 'org.springframework.security.core.context.SecurityContextImpl@ece7b0b7: Authentication: ...
    06.10 14:42:26 DEBUG - context.SecurityContextPersistenceFilter(SecurityContextPersistenceFilter.java:89) -  - SecurityContextHolder now cleared, as request processing completed
    06.10 14:42:26 DEBUG - servlet.DispatcherServlet(DispatcherServlet.java:691) -  - DispatcherServlet with name 'foo' processing GET request for [/foo/app/error/403.html]
    

    So either Spring or Tomcat redirect to an error page and the request gest finalized, thus the context is cleared. And the new "request" doesn't undergo Spring Security filters, thus not restoring the context.

    The usual way doesn't work, but it seems that the authentication information is somewhere in the session, also because AbstractTemplateView logs the following:

    Exposing session attribute 'SPRING_SECURITY_CONTEXT' with value [org.springframework.security.core.context.SecurityContextImpl@edfbd958: Authentication: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@edfbd958...
    

    How do I properly get so that both normal and error pages would act the same?

  • Infeligo
    Infeligo almost 13 years
    Thanks! I accepted your answer because it gave me the right input: ExceptionTranslationFilter is the guy that handles exceptions. It has accessDeniedHandler property, which is by default an instance of AccessDeniedHandlerImpl. Luckily it has an errorPage property and the documentation states, that "being a "forward", the SecurityContextHolder will remain populated." I rewired my beans and it worked!
  • David van Laatum
    David van Laatum over 8 years
    This got it to work for me error page now knows if you are logged in or not