Remember Me Functionality in Apache Wicket
It is quite common in web applications to have “Remember Me” functionality that allows user to be automatically logged in each time when he visits our website.
Such feature can be implemented using Spring Security, but in my opinion using request based authentication framework with component based web framework is not the best idea. These two worlds just do not fit well together so I prefer to use my own baked solution which I will present below.
Base application consists of two pages:
Home Page: displays welcome message for logged and not-logged users or either logout or login link.
Login Page: allows user to login basing on simple in-memory collection of users. Some working login/password pairs: John/john, Lisa/lisa, Tom/tom .
Remember Me functionality
Standard way to implement Remember Me functionality looks as follows:
Ask user if he wants to be remembered and auto-logged in the future.
If so, save cookies with login and password on his computer.
For every new user coming to our website, check if cookies from step 2 are present and if so, auto login user.
When he manually logs out, remove cookies so it is possible to clear data used to auto-login.
Point 2 needs some explanation. In this example app we are going to save login and not hashed, not encrypted password in cookies. In real scenario this is unacceptable. Instead of it, you should consider storing hashed and salted password so even if someone intercepts user cookie, password still will be secret and more work will be needed to decode it. Update: Michał Matłoka posted two very interesting links how this could be done in real systems. Those approaches do not even use password nor password hashes. For more details please look into his comment below this post.
Step 1: As a User I want to decide if I want to use “Remember Me” feature Link to commit with this step
To allow user to notify application that he wants to use ‘Remember Me’ functionality we will simply add a checkbox to login page. So we need to amend LoginPage java and html file a bit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Now we are ready for next step.
Step 2: As a System I want to save login and password in cookies Link to commit with this step
First we need a CookieService that will encapsulate all logic responsible for working with cookies: saving, listing and clearing cookie when needed. Code is rather simple, we work with WebResponse and WebRequest classes to modify cookies in user’s browser.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
Then when user checks ‘Remember Me’ on LoginPage, we have to save cookies in his browser:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Step 3: As a User I want to be auto-logged when I return to web application Link to commit with this step
To check if user entering our application is a “returning user to auto-login” we have to enrich logic responsible for creating new user session. Currently it is done in WicketApplication class which when requested, creates new WebSession instance. So every time new session is created, we have to check for cookies presence and if they are valid user/password pair, auto-login this user.
So let’s start with extracting session related logic into separate class called SessionProvider. It will need UserService and CookieService to check for existing users and cookies so we pass them as a references in the constructor.
1 2 3 4 5 6 7 8 9 10 11
Role of SessionProvider is to create new UserSession, check if proper cookies are present and if so, set logged user. Additionally we add feedback message to inform user that he was auto logged. So let’s look into the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
To show feedback message on HomePage.java we must add FeedbackPanel there, but for the brevity I will omit this in this post. You can read commit to check how to do that.
So we after three steps we should have ‘Remember Me’ working. To check it quickly please modify session timeout in web.xml file by adding:
1 2 3
and then start application mvn clean compile jetty:run, go to login page, login, close browser and after over a 1 minute (when session expires) open it again on http://localhost:8080. You should see something like this:
So it works. But we still need one more thing: allow user to remove cookies and turn-off auto-login.
Step 4: As a User I want to be able to logout and clear my cookies Link to commit with this step In the last step we have to allow user to clear his data and disable “Remember Me” for his account. This will be achieved by clearing both cookies when user explicitly clicks Logout link.
1 2 3 4 5 6 7 8 9 10 11 12 13
So that’s all. In this port we have implemented simple ‘Remember Me’ functionality in web application written using Apache Wicket without using any external authentication libraries.
How-to, Java, Wicket