In Rails, call reset_session after a successful login to prevent session fixation, store only an identifier in the cookie session, expire sessions on the server side, and set config.force_ssl = true. Those four habits cover most of what the Rails security guide says about sessions.
How Rails stores sessions by default
The guide says Rails uses ActionDispatch::Session::CookieStore by default. The session data is encrypted, and the keys derive from secret_key_base. You can generate a new secret with bin/rails secret.
Encrypted does not mean unlimited. A cookie has a size cap, and anything you put in it travels with every request.
Store an ID, not state
The guide's advice is to keep durable or sensitive data in the database and put only an identifier, like a logged_in_user_id, in the session. Its example is credits: do not keep a balance in the session, because a user could replay an older cookie that holds a higher number.
Reset the session at login
Session fixation works like this: an attacker gets a victim to use a session ID the attacker already knows, then waits for the victim to log in. If the ID survives the login, the attacker is now logged in too. The guide's countermeasure is to call reset_session after a successful login, so the identifier changes at the moment privilege changes.
def create
user = User.authenticate(params[:email], params[:password])
if user
reset_session
session[:user_id] = user.id
redirect_to root_path
end
end
Treat the same moment, any privilege change, as a reason to reset.
Expire on the server
A cookie that says it expires in 20 minutes is only a request to the browser. The guide recommends expiring sessions on the server. Its example is a sweep that deletes sessions whose updated_at is older than a cutoff, and it also says to delete by created_at so an attacker cannot keep a stolen session alive forever by touching it.
Force SSL
Set config.force_ssl = true so cookies are protected in transit.
CSRF belongs in the same conversation
Use protect_from_forgery with: :exception, which the guide says new apps enable by default, and include csrf_meta_tags in the layout so Turbo and JavaScript requests send the token. Use GET for safe, read-only actions and POST, PATCH, PUT or DELETE for changes.
Quick check
Is an encrypted cookie session safe for storing a user role?
It is safer to store only the user ID and look the role up each request, so role changes take effect immediately.
Does reset_session log the user out?
It clears the session, so call it before you set the new login values, as in the example above.
Sources
Last reviewed: 19 October 2026.