User sessions with Rails 5

User sessions allow you to keep track of a particular user of your application and store data against that in some way. The most typical reason is to track an authenticated user that has lots of privileges on the system vs another person who has less access.

In Rails we can create and maintain sessions in a number of ways. I'm going to explore the theory of a simple method that makes use of sessions and cookies. Using a session we'll create a disposable user authenticated session and using cookies we'll make the session persistent.

Sessions, for one night only

Any time a user visits your rails site, a "session" is placed on their machine. The session is a place that we can store small bits of data. In fact it's actually just a type of cookie, this is why like cookies the storage capacity is 4kb max!

Sessions are very easy to set up, a simple way to start is by assigning the user id to the session. Rails encrypts browser sessions by default which is great.

# Log the user in by creating a session
session[:user_id] = user.id

The important thing to remember about Sessions is that they will be destroyed after the web browser is closed. This means a user can log in, we can store their session from request to request, however if they shut down their computer then next day the session will no longer exist. This is okay, and very useful for users wanting a single session, say on a public computer, but not so great for the average joe.

The session forms the baseline for our user sessions. What we can add on top is a persistent session.

Cookies, the biscuit of persistence

Cookies stay on the users machine until they either expire or the user clears them out. This means they're remain alive across browser closes, as a result we can use this for persistent user sessions.

The trick to a persistent user session is to generate a session id when the user ticks the option to remember them. When that has been generated you can assign that to the user either in your users database or in a separate session store. You then take that ID and the user ID and place them into a long life cookie on the users browser.

When doing this, make sure that the user ID is encrypted by Rails. You can do this using the signed function like so:

# Log the user in by creating a session
session[:user_id] = user.id

# If the user has asked you to remember them
# then generate a session_id and assign it to
# them in the database or session store and
# attach it to the user object for ease of use
# later.

# Assign both ID's as permanent cookies
cookies.permanent.signed[:user_id] = user.id
cookies.permanent[:session_id] = user.session_id

With that done, we now have two options when looking for a logged in user.

  1. Check if the user has a session. If they do then we're in action and can use the user id from there.
  2. If no session exists, then we can check for the presence of our cookies. After validating the cookies we can then give the user another session to use in subsequent requests.

Using this flow we can default to disposable sessions which destroy when the browser closes. On top of that if the user trusts the machine, such as their own laptop, then we can store some persistent but secured data in cookie form.