my thoughts on programming and other nerdy stuff

How to implement a Session Timeout in Play Framework 2


If you fol­low the Play Frame­work 2 guide for imple­ment­ing authen­ti­ca­tion: http://​www​.playframe​work​.com/​d​o​c​u​m​e​n​t​a​t​i​o​n​/​2​.​2​.​2​/​J​a​v​a​G​u​i​de4 — you will notice that there is no ses­sion time­out in Play Frame­work 2. It was there in Play Frame­work 1, but Play Frame­work 2 fol­lows a dif­fer­ent approach.

I you want to imple­ment your own ses­sion time­out, then fol­low the guide for set­ting up authen­ti­ca­tion, by extend­ing the Security.Authenticator, and store a time­stamp in the ses­sion and keep extend­ing it every time a request is made.

Here is how I did it:

public class Secured extends Security.Authenticator {

    public static final String UNAUTHENTICATED = "unauthenticated";

    public static User getLoggedInUser() {
        if (session("userId") == null)
            return null;
        return User.findById(Long.parseLong(session("userId")));

    public static String getLoggedInUsername() {
        if (session("userId") == null)
            return null;
        return User.findById(Long.parseLong(session("userId"))).getUsername();

    public String getUsername(Http.Context ctx) {

        // see if user is logged in
        if (session("userId") == null)
            return null;

        // see if the session is expired
        String previousTick = session("userTime");
        if (previousTick != null && !previousTick.equals("")) {
            long previousT = Long.valueOf(previousTick);
            long currentT = new Date().getTime();
            long timeout = Long.valueOf(Play.application().configuration().getString("sessionTimeout")) * 1000 * 60;
            if ((currentT - previousT) > timeout) {
                // session expired
                return null;

        // update time in session
        String tickString = Long.toString(new Date().getTime());
        session("userTime", tickString);

        return User.findById(Long.parseLong(session("userId"))).getUsername();

Then just add a sessionTimeout=15 (in Min­utes) to your conf file.

If you have read this far, you may as well fol­low me on Twit­ter:

Author: poornerd

Tech­nol­o­gist, Entre­pre­neur, Vision­ary, Pro­gram­mer :: Grad­u­ated from USC (Uni­ver­sity of South­ern Cal­i­for­nia) with a degree in Com­puter Sci­ence. After 10+ years of free­lance con­sult­ing and pro­gram­ming, he co-founded Site­Force AG eBusi­ness Solu­tions in 1999 in Munich (München), Ger­many.


  1. Really nice one…Thanks..if u have spare time please make a scala version..

  2. Is this time­out for idle time? I believe it’s max time­out for the ses­sion itself rather than the idle time. Which means the ses­sion will be cleared after that par­tic­u­lar time even if the user is active right? Can you sug­gest me the way to do it for idle time?

    • This is sort of for Idle time, because if you don’t do any­thing for the dura­tion of the time­out, then your next request will deter­mine that the ses­sion has expired and not allow any secured actions to be exe­cuted until the user has been authen­ti­cated again. What you are describ­ing is the Play Frame­work 2’s builtin time­out, that is fixed, and will expire even if the user is active — this of course is the rea­son for my implementation!

      I sup­pose it would also be pos­si­ble to cre­ate a sep­a­rate ses­sion time­out cookie, that actu­ally expires… but I think this way is sufficient.

      If you were cre­at­ing a scaleable archi­tec­ture, you would have a dis­trib­uted cache in use (like mem­cached), so the ses­sion would apply every node of the cluster.

  3. I am not a user of Play! so I may miss some­thing but from your code I see that you clear the ses­sion when a request to #getUser­name() is made and the dura­tion of the last accessTime is big­ger than the timeout.

    But this makes me ask myself: what if the user never makes a new request and thus #getUser­name() is not called for this user ? Who will clear the ses­sion in this case ?

    • Play Frame­work stores the Ses­sion in a Ses­sion cookie, so it is never stored on the server any­ways. If the user closes his browser, then the ses­sion is also cleared. So tech­ni­cally the ses­sion is not tim­ing out, but I am forc­ing the user to have to log back in after a period of inactivity.

  4. Does Play Frame­work 2 offer the abil­ity to be hosted from an inde­pen­dent server over than it’s own? Try­ing to build an appli­ca­tion where Play does not do the host­ing.

  5. Nice post !
    I just made a method out of all of this, cur­rently using it in my app,
    works won­der­fully!
    pub­lic boolean isSessionNotExpired(Http.Context ctx){
    Long last­Ses­sion­Time;
    last­Ses­sion­Time = Long.valueOf(ctx.session().get(SessionsKey.USER_TIME));
    } catch (Num­ber­For­ma­tEx­cep­tion e){
    return false;
    boolean not­Ex­pired = lastSessionTime+SESSION_MILLIS_TIMEOUT_VALUE > new Date().getTime();
    if (not­Ex­pired)
    session(SessionsKey.USER_TIME, Long.toString(new Date().getTime()));
    return not­Ex­pired;

  6. Hi Brian,

    Thanks for this post. How do we make sure the user is always signed in unless he/she explic­itly signs out? Basi­cally a Remem­ber Me on this machine kind of fea­ture in Play 2

    • It is a ses­sion cookie. So if the user closes the browser he is logged out as well. Does that answer the ques­tion? I sup­pose you could change the cookie to not be a ses­sion cookie, but then you can just use Play’s builtin ses­sion man­age­ment if you do not need the timeout.

  7. We use play 2.1.3, when I close the browser the ses­sion gets expired after 15 mins.

    If I try to open the appli­ca­tion in the browser again before 15 mins, I am able to see the home page already being logged-in.

    When the user closes the browser and after 15 mins when the ses­sion gets expired I want to log that as ‘logout’ event in the DB.

    How can I do that ? Is there any call­back func­tions that we can setup in the play server to get called after the idletimeout ?


Leave a Reply

Required fields are marked *.