1

Currently, the logic for my application is that, when the user's password expires after for example, 30 days, a user will be redirected to the Change Password screen even if they were in the middle of doing something. This is wrong. The user should only be prompted to change their password on the next login.

I have created a CheckAfterLoginFilter which extends OncePerRequestFilter where the logic resides. However, this is filtered on EVERY request so that user logs out in mid session. I am not sure how I can implement the desired logic in here if it's even possible.

My login form jsp uses j_security_check. My first thought was to move the logic from CheckAfterLoginFilter into the LoginController but j_security_check seems to redirect to it's own thing which I have no idea about or where to find.

Some help would be much appreciated!

Thanks

Cath
  • 23,906
  • 5
  • 52
  • 86
Johnathan Au
  • 5,244
  • 18
  • 70
  • 128

2 Answers2

6

As you are using Spring Security, I'd assume you have already configured authenticationManager, and your UserEntity implements UserDetails.

My suggestion would be to provide custom authentication failure handler and override isCredentialsNonExpired() in your UserEntity.

Here is an example (with java based configurations).

Custom authentication failure provider

@Bean
public AuthenticationFailureHandler customAuthenticationFailureHandler() {
    ExceptionMappingAuthenticationFailureHandler exceptionMappingAuthenticationFailureHandler =
            new ExceptionMappingAuthenticationFailureHandler();
    Map<Object, Object> map = new HashMap<>();
    map.put(
            "org.springframework.security.authentication.CredentialsExpiredException",
            "/resetPassword.html"
    );        

    exceptionMappingAuthenticationFailureHandler.setExceptionMappings(map);

    exceptionMappingAuthenticationFailureHandler.setRedirectStrategy(
            new RedirectStrategy() {
                @Override
                public void sendRedirect(
                        HttpServletRequest request, HttpServletResponse response, String url
                ) throws IOException {
                    response.sendRedirect(request.getContextPath() + url);
                }
            }
    );

    return exceptionMappingAuthenticationFailureHandler;
}

XML way

<bean id="customAuthenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
    <property name="exceptionMappings">
        <props>
            <prop key="org.springframework.security.authentication.CredentialsExpiredException">/change_password_page</prop>
        </props>
    </property>
    <property name="defaultFailureUrl" value="/resetPassword"/>
</bean>

and in your security.xml

<security:form-login ... authentication-failure-handler-ref="customAuthenticationFailureHandler">

And finally in your UserEntity

    @Override
    public boolean isCredentialsNonExpired() {
        if (// check password is expired or not) {
           return false;
        }
        return true;
     }

So when password expires, failure handler will redirect to your desired page.

vtor
  • 8,989
  • 7
  • 51
  • 67
0

Allow the expiry date to be say 31 days when checking in the servlet filter but only 30 days when doing the login.

So when it hits the servlet filter after 30 days it will keep on going as for up to another day but if they haven't changed their password by 31 days you want them to be logged out anyway.

Astra Bear
  • 2,646
  • 1
  • 20
  • 27