Spring-security: SEC-2200: ExceptionTranslationFilter not handling IS_AUTHENTICATED_FULLY in remember-me situation

Created on 10 Jul 2013  路  2Comments  路  Source: spring-projects/spring-security

Fred Allard (Migrated from SEC-2200) said:

If a user is authenticated in a remember-me use case and trying to access an url which requires a full authentication (access=IS_FULLY_AUTHENTICATED), the AuthenticatedVoter throws an AccessDeniedException. That works fine.

The ExceptionTranslationFilter catch the exception and instead of redirecting the user to the authentication strategy configured, the filter returns a 403 error. That doesn't work.

Maybe it's a problem in my configuration, but I think the problem is here in the ExceptionTranslationFilter :

    private void handleSpringSecurityException(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
            RuntimeException exception) throws IOException, ServletException {
        if (exception instanceof AuthenticationException) {
            logger.debug("Authentication exception occurred; redirecting to authentication entry point", exception);

            sendStartAuthentication(request, response, chain, (AuthenticationException) exception);
        }
        else if (exception instanceof AccessDeniedException) {
            if (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication())) {
                logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point",
                            exception);

                sendStartAuthentication(request, response, chain, new InsufficientAuthenticationException(
                        "Full authentication is required to access this resource"));
            }
            // !!!! The remember-me should be handled here.
            else {
                logger.debug("Access is denied (user is not anonymous); delegating to AccessDeniedHandler", exception);

                accessDeniedHandler.handle(request, response, (AccessDeniedException) exception);
            }
        }
    }

Here is my configuration :

  <http authentication-manager-ref="authenticationManager"
        access-decision-manager-ref="accessDecisionManager">
    <anonymous username="anonymousUser" granted-authority="ROLE_ANONYMOUS" />

    <remember-me token-validity-seconds="604800" 
                 key="thisisatestkey"
                 use-secure-cookie="false" 
                 remember-me-parameter="remember" />

    <intercept-url pattern="/home/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <intercept-url pattern="/inventory/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <intercept-url pattern="/security/login.htm" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="http" />
    <intercept-url pattern="/sale/**" access="IS_AUTHENTICATED_FULLY" />

    <port-mappings>
      <port-mapping http="8080" https="8443" />
    </port-mappings> 

    <access-denied-handler error-page="/security/error.htm" />

    <form-login login-page="/security/login.htm"
                login-processing-url="/security/authenticate"
                username-parameter="username"
                password-parameter="password" />

    <logout logout-success-url="/home/home.htm"
            logout-url="/security/logout" />

    <expression-handler ref="webExpressionHandler" />

    <session-management invalid-session-url="/security/login.htm" session-fixation-protection="migrateSession">
      <concurrency-control max-sessions="2" /> 
    </session-management>
  </http>

  <authentication-manager id="authenticationManager" erase-credentials="true">
    <authentication-provider>
      <!--password-encoder hash="bcrypt" /-->
      <user-service>
        <user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN" />
        <user name="user" password="user" authorities="ROLE_USER" />
      </user-service>
    </authentication-provider>
  </authentication-manager>  

  <beans:bean id="webExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />

  <beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
    <beans:constructor-arg>
      <beans:list>
        <beans:bean class="org.springframework.security.access.vote.RoleVoter" />
        <beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
      </beans:list>
    </beans:constructor-arg>
  </beans:bean>

I've joined a fix proposal.

web bug jira

All 2 comments

Rolf Schenk said:

Same issue with my remember-me configuration:

access="isFullyAuthenticated() and hasRole('ROLE_USER')"/>

ROLE_USER is granted by remember-me, isFullyAuthenticated is false as expected.
On page access, a 403 is raised by the ExceptionTranslationFilter cuz the request is no longer anonymous:

ExceptionTranslationFilter probes for authenticationTrustResolver.isAnonymous but should check also for authenticationTrustResolver.isRememberMe. Also for isRememberMe case a sendStartAuthentication is expected.

Unfortunately, when (with this latest change) remember-me authenticated user tries to access something with access="hasRole('ROLE_SOMETHING')", (s)he will be handled with sendStartAuthentication instead of accessDeniedHandler. Is this expected behavious or just an unfortunate side-effect?

Was this page helpful?
0 / 5 - 0 ratings