SPA Session Timeout — Vue + Rails Implementation
In-depth guide to implementing a single-page application(SPA) session timeout using Vue & Rails.
In-depth guide to implementing a single-page application(SPA) session timeout using Vue & Rails.
This is an in-depth guide to implementing a single-page application(SPA) session timeout using Vue & Rails. Despite all examples using Vue & Rails, the architecture we’re about to go through can be implemented in pretty much any server/client stack.
Don’t worry! This is a pretty small build that you can finish in an hour or two so let’s roll up our sleeves and get started!
Before diving straight into code, let’s take a brief look at what we’re building.
Terminology
Each request by a context has a time, and if that time exceeds the timeoutthen the session is destroyed, otherwise a new timeout is committed and the request proceeds as expected.
In simpler terms, as a user is clicking around your Vue app requests are being made to your Rails server. Each request serves as a signal to the server to keep that users session active. If no requests are made in a given time period, say 15 minutes for example, then the user’s session has timed out.
Now that we know what we’re building, let’s dive into Rails and make the necessary changes to our server!
In order to implement our session timeout our server must be prepped to match the above guidelines. Relax, this is a very small amount of code.
Models
A User model with the datetime attribute timeout will be used in this example. It’s okay to leave the default of this attribute as nil. We’re also adding the following functions to our User model which will help set a 15 minute timeout.
Controllers
On our server we need to plug in a filter which will process our session timeouts on each request. Note that we will be making use of the Login Time-Out HTTP Error Code 440 to signal to the client that a session has timed out. In Rails 6, a filter on every request will look something like:
At this point our server should actually have a working session timeout. You should be able to manually GET one of your routes to test the timeout. However, there’s still a bit of work to do to ensure our client responds to the session timeout correctly. Let’s move over to our client!
Now that the server is prepped for session timeouts, it’s time to configure the client. You’ll want to add the idle-vue library to your project as we will be making use of it momentarily.
Axios Configuration
At a base level it’s important to have a fallback case which checks for the session timeout error code we implemented earlier. In axios this can be accomplished with an interceptor.
IdleVue Configuration
Next, we’ll want to ensure the client knows to time out after 15 minutes of inactivity. We’re going to make use of idle-vue to accomplish this task. In your main.js file, add the following:
In the above we’re making use of the onIdle hook idle-vue provides us to sign users out after 15 minutes of inactivity. While this solution is simple, it’s also functional. We’ll briefly cover a more advanced solution in the Usability Improvements section below.
At this point you should have a working client/server timeout! Great work! At 15 minutes of inactivity your client should redirect the user back to your Signin page, and if for some reason that trigger isn’t hit we have a fallback looking for the timeout error code which will do the same. By design, our server will track session timeouts regardless of client activity. This is crucially important as even if users close and reopen their browsers their session timeout is maintained. In short, the session timeouts are authoritative and secure!
At its core the session timeout system we just implemented is functional, but it’s not very user friendly. Luckily, idle-vue gives us multiple activity hooks in which we can implement usability features. For instance, if you’d like a popup to appear 60 seconds before a user is signed out then we can easily plug this into our existing idle-vue configuration.
In order to get a popup to appear before a user is signed out we should set our idleTime to 14 minutes instead of 15. Then, onIdle, instead of just signing the user out we can show a popup which should sign the user out after 60 seconds. Finally, in the idle-vue onActive hook we can close the popup and send a request to our server to keep our session alive. You can read more about the idle-vue hooks at their github repo.
I hope this guide provides some much needed insight into the SPA session timeout problem. At its core, this is the exact session timeout system we designed and implemented at Nucla on our professional business products. There are many potential solutions to the SPA session timeout problem, but we felt the above was just the correct mix of simple and secure we needed.