Spring Security Remember Me

This post follows the Spring Security Simple Authorization post, but also adds the remember-me functionality to our application.

Like before, we ask the user for his credentials. If correct, he enters to the dashboard. If wrong, he gets error message. We have two user roles, the simple user who can access only the dashboard, and the admin who can access the dashboard and the admin page. If a simple user try to access the admin page, he will get redirected to the 403 page.

If a user check the remember-me checkbox on the login form, a cookie will be stored to the browser. As long as the cookie is active, the user can enter to the application without login.

The user has restricted authorization when he is authenticated using the remember-me cookie, for security purposes. This can be tested at the profile page where the remember-me authenticated user cannot change his password.

The full github repository can be found here: SpringSecurityRememberMe

Technologies Used

  • Spring MVC
  • Spring Security
  • Hibernate
  • MySQL
  • Maven
  • Jsp , Jstl

Database

The database structure, that we have already, will remain the same as we don’t need any changes on the user or the role table. We just have to add an extra table named persistent_logins, which will contain the username and the remember-me tocken information. 

CREATE TABLE role
(
  role_id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(200) NOT NULL,
  UNIQUE (name)
);


CREATE TABLE user
(
  user_id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT ,
  username VARCHAR(400) NOT NULL,
  password VARCHAR(400) NOT NULL,
  role_id BIGINT,
  FOREIGN KEY (role_id) REFERENCES role(role_id)
);

create table persistent_logins
(
  username varchar(64) not null,
  series varchar(64) primary key,
  token varchar(64) not null,
  last_used timestamp not null
);


INSERT INTO role (name) VALUE("USER");
INSERT INTO role (name) VALUE("ADMIN");


INSERT INTO user (username, password, role_id) VALUES ("testUser", "$2a$10$04TVADrR6/SPLBjsK0N30.Jf5fNjBugSACeGv1S69dZALR7lSov0y",1);
INSERT INTO user (username, password, role_id) VALUES ("testAdmin", "$2a$10$04TVADrR6/SPLBjsK0N30.Jf5fNjBugSACeGv1S69dZALR7lSov0y",2);

 

Implementation

The first and most important change takes place on the spring security configuration, where we must declare the remember-me functionality. We place it inside the http tag and configure the expiration time of the token, the authentication provider, the parameter that we will use to the checkbox and the data source reference.

spring-security.xml

<http auto-config="true" use-expressions="true">

    <intercept-url pattern="/dashboard**" access="isAuthenticated()" />
    <intercept-url pattern="/admin**" access="hasAuthority('ADMIN')" />

    <access-denied-handler error-page="/403" />

    <form-login
        login-page="/login"
        default-target-url="/dashboard"
        authentication-failure-url="/login?error"
        username-parameter="username"
        password-parameter="password" />

    <logout logout-success-url="/login?logout" />

    <remember-me
            token-validity-seconds="1209600"
            user-service-ref="userDetailsService"
            remember-me-parameter="rememberMe"
            data-source-ref="dataSource" />

</http>

 

After that, we need to add the remember me checkbox to our login form.

login.jsp

<c:url var="post_url" value="/j_spring_security_check" />
<form:form  action ="${post_url}" method='POST' commandName="loginForm">
    <h2 class="form-signin-heading">Welcome!</h2>
    <label for="inputUsername" class="sr-only">Username</label>
    <form:input path="username" id="inputUsername" placeholder="Username" size="30"/>
    <form:errors path="username" cssClass="error"/>

    <label for="inputPassword" class="sr-only">Password</label>
    <form:password path="password" id="inputPassword" placeholder="Password" size="30"/>
    <form:errors path="password" cssClass="error"/>

    Remember me : <form:checkbox path="rememberMe" id="inputRememberMe"/>

    <button class="btn btn-lg btn-primary btn-block" type="submit">Login</button>
</form:form>

 

We can also restrict the access of a user who has entered the application using the remember-me cookie for security purposes. Remember-me is handy but can also be dangerous, in cases that more than one people uses the same devices. That’s why we should restrict the pages that contain sensitive data or actions, like the change password page.

profile.jsp

<div class="container">
    <div class="starter-template">

    <h3>Change Password</h3>

        <sec:authorize access="isRememberMe()">
            <h2> You are authenticated with Remember Me. You need to login again to change your password. </h2>
        </sec:authorize>
    
        <sec:authorize access="isFullyAuthenticated()">
            <button>Change password</button>
        </sec:authorize>
    </div>
</div>

 

Installation and Run

  • Run the database/queries.sql  queries to your database.
  • Add your database credentials to resources/db.properties file.
  • Build the project using mvn clean install
  • Run the application using tomcat

Test Credentials

Username Password Role
testUser 123456 user
testAdmin 123456 admin