poornerd

my thoughts on programming and other nerdy stuff

How to implement a Session Timeout in Play Framework 2

| 9 Comments

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();
    }


    @Override
    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
                session().clear();
                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.

9 Comments

  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.
    thanks,

Leave a Reply

Required fields are marked *.