Banishing “Your Session Has Expired” from the Internet

It’s hard to use the web without coming across “Your Session Has Expired” at least a few times a year. Maybe you’re trying to book a flight, or reserve tickets for a concert. You could be trying to do some online banking, submit an application to a university, or use some enterprise software. When a session expires, you’re typically dumped at an error page (not even a login page!), all the data you’ve entered so far is dropped, and you’re forced to start over. When it occurs, it’s one of those user experiences that makes me, the user, feel incredibly stupid, even though it’s the site that’s at fault.

session-has-timed-out

“Your session has timed out” is a symptom of a security feature. It’s designed to stop attackers from mimicking the sessions of logged in users by destroying those sessions. It’s often used with things like ecommerce checkout flows. Sometimes it’s used to cope with the time-sensitive nature of buying tickets.

But!

This pattern has ended up baked into so many web development frameworks, that it now frequently shows up in regular webapps. This now happens even if the site has no commerce, no banking, no tickets: pretty much nothing that warrants session time-outs at all.

If you’re a site owner that remotely cares about user experience, please take a good hard look at why you’re expiring sessions!

A lot of the thinking and defaults around sessions and expiry were created as the web was first scaling up. This was when scaling a server was a big scary deal: the cloud wasn’t a thing yet. Having lots of these sessions around might kill your scalability in 2001, so if a user hasn’t accessed a page for some number of minutes, their session could be killed dead in favor of active users that are accessing the site right now.

But for countless sites scaling isn’t necessarily their biggest challenge. Even when it is, session storage is very rarely the first thing that’s going to solve all your scaling woes. Which begs the questions:

  1. What should be done to address this infuriating user experience without compromising on security or scalability?
  2. How do we take action to banish this error from the web frameworks that most developers are using?

If your site already uses session timeouts, I want to help you analyze if it even needs to. If it does, I’ve collated the ways to change session expiry behavior for a range of web frameworks, below. I want to help get rid of the dreaded “your session has timed out” error page from every corner of the Internet.

What should be done

The first thing to do is a back-of-the-envelope risk analysis of your site. Do you need to forcibly expire users after a certain amount of time, simply because they stepped away from their desk? Ask yourself whose security, if anyone’s, is compromised if you don’t? If your site’s member area only shows fantasy football results, it’s unlikely you need to be forcibly expiring users’ sessions! You can probably configure infinite or lengthy session timeouts safely.

Similarly, what are your scaling properties – is session storage a bottleneck you’ve encountered? Do you know anyone who’s encountered server session storage as a scaling bottleneck in the last 10 years? Didn’t think so. Go ahead and stop expiring sessions under the abstract fear of some “scaling” bogeyman.

Timeout Prompt

Even if you do need to forcibly expire sessions, there’s no reason to keep the user in the dark about it. HSBC’s online banking lets the user know that their session is going to timeout in a minute, and offers the user a quick and easy way to keep their session going without having to log in again. It’s not an ideal approach: if the user has taken a comfort break or left their desk for lunch, they’re not going to see a pop-up that only lives for 60 seconds. But it is a step in the right direction.

The popup approach creates a user experience that tries not to treat the user’s session as something that “the system” can terminate in the background without consulting the person using it. This at the very least reduces the user’s feeling of powerlessness.

How to change session defaults

The prompt to extend a user’s session can be dropped into any application using the jQuery.sessionTimeout plugin. But by far the simplest way to fix the session expiry problem is stop using sessions that only last 20 minutes, an hour, or some other short duration.

Although extending session expiry only addresses the symptom and not the cause, it will at least mean people can stop losing data just for taking a lunch break! I’ve included instructions below for changing the default session expiry/timeout for webapps written in Java, PHP, Django, Play, Rails, Sinatra/Rack, Node.js express, ASP.net and Coldfusion.

Java servlets, JSPs, Struts, Grails, etc.

In your application’s web.xml file (aka the deployment descriptor) you can set a custom timeout in minutes. The servlet spec dictates that setting the timeout to zero or less ensures the session will never expire, this is honored by Tomcat.

<session-config>
    <session-timeout>10080</session-timeout> <!-- 1 week, in minutes -->
</session-config>

PHP Symfony

By default this PHP framework sets the session cookie’s timeout to only expire when you close the browser. If you’ve already set it to something low, edit this setting in your app/config/config.yml file:

framework:
    session:
        cookie_lifetime: 604800  # 1 week, in seconds

PHP Rolled-your-own

If you’ve rolled your own session system, you probably implemented expiry of some kind. If you set the default to something low like 20 minutes, try increasing it to a few hours and see if it has any negative impact on your service. If not, boost it further! This StackOverflow answer tries to go into detail on some of the settings that PHP makes use of for sessions, but the situation seems messy. Please post a comment if you know a good general solution.

Django (python)

Django has some subtlety to its session behavior but by default sessions persist for upto 2 weeks. The full fine-grained detail can be found in the documentation.

Play (Scala)

Check your conf/application.conf file. By default, session cookies in Play expire with the browser window: that’s much better than an explicit short session age. If your application already has a session expiry, change its duration by looking for this line:

application.session.maxAge=7d // Remove this line for better session expiry

Rails

Rails doesn’t mandate a session expiry by default. If you’re working on a large application you might want to search your codebase to see if one has been configured already. If your app has one, it’s probably doing something funky in a before_filter, or by using a global call like this:

 Yourapp::Application.config.session_store :cookie_store, 
                                           :key => "_yourapp_session",
                                           :expire_after => 1.week

By removing the :expire_after your sessions should last as long as the browser window is open.

Sinatra/Rack

This lightweight ruby web framework wraps sessions with a simple enable :sessions call. Its defaults don’t include any session expiry but if your application already has expiry configured, it’s probably been set up using Rack::Session::Cookie directly and probably has a needlessly short expiry. To increase the timeout, check the :expire_after property:

use Rack::Session::Cookie, :key => 'rack.session',
                           :domain => 'YOUR_DOMAIN_HERE',
                           :path => '/',
                           :expire_after => 7*24*60*60, # 7 days (seconds)
                           :secret => 'YOUR_SESSION_SECRET_HERE'

Run SecureRandom.hex(64) from an irb console to generate a secure session secret if you don’t already have one.

Node.js express

Similar to the Rack based method of sinatra, above, Express takes a middleware-style approach to configuring sessions, (thanks stackoverflow):

var express = require('express');
var app = express();

app.use(express.session({
  key : 'whynode',
  store : sessionStore,
  cookie: { 
    maxAge: 31*24*60*60*1000 // 31 days, in milliseconds
  }
}));

ASP.net

This can be easily changed from the default 20 minutes by ensuring the sessionState element is present in your web.config file, (thanks stackoverflow):

<configuration>
     <system.web>
         <sessionState timeout="10080" /> <!-- 1 week, in minutes -->
     </system.web>
</configuration>

Coldfusion

Configure the default session timeout by using the sessionTimeout attribute in your cfapplication tag. You’ll also want to check (and potentially change) the maximum session timeout value on the Administrator Memory Variables page of your server. The attribute value here can’t be longer than the admin page.

<cfapplication  
 sessionTimeout = #CreateTimeSpan(days, hours, minutes, seconds)#

Are you the author of a popular framework? Email me your instructions and I’ll add them to this section.

Have you banished your expiry now?

Not every single session timeout is bogus. But 99% of them are. Most are too short by far and haven’t even considered the soul-crushing impact on user experience. Next time someone tells you “we need a short session timeout… for… security! scalability! other!”, challenge them to explain exactly what they mean in precise technical detail.

And then please, post their answer in the comments below. 🙂

to hear about future posts, front-end development tools, hints, tips, and cutting-edge hacks.

Advertisement
This entry was posted in HOW-TOs, Tools. Bookmark the permalink.

3 Responses to Banishing “Your Session Has Expired” from the Internet

  1. Manys says:

    I can entirely sympathize, but just to provide one example, the one that brought me to this page :), I am using it in an educational app where it provides an end-time for study sessions where the user doesn’t explicitly log out, and also a little idiot-proofing where a student does not log out before the next class comes in. It’s similar to the banking use-case, I guess, but without security implications.

  2. Brett Havener says:

    We have an in house application that not only times out the session, it times out the login page that the timeout takes you to. I find the login page timeout even more annoying because at least I can understand the security reason to timeout the session for this application. Can anyone please explain to me why you would ever timeout a login page?

  3. Dan says:

    I’ve used a website that maintained sessions even though you didn’t log into it. If you went to the page and let the page sit for 10 minutes then clicked on any link it would take you to a “session expired” page.

    On the other side, we use a web-based accounting package at work. If the sessions are long there are security issues, but if the session is what it should be to prompt for authentication, there’s a dataloss issue. There really needs to be a way to prompt for auth and use the form data instead of just throwing it away. Users shouldn’t need to know what a session is or realize it has expired.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s