Understanding Sessions in Ruby on Rails — Ruby Deep Dive[17]

Bhavyansh @ DiversePixel
4 min readAug 3, 2024

--

Sessions in Ruby on Rails are a fundamental part of maintaining state and storing temporary user data across multiple HTTP requests. This is crucial for web applications that require user authentication, shopping carts, and other state-dependent interactions. In this article, we will explore the purpose, mechanisms, configurations, security, and best practices for using sessions in Rails.

Purpose of Sessions

Sessions are used to:

  • Store Temporary User Data: Keep user-specific data that needs to persist across requests, such as user IDs or preferences.
  • Maintain User State: Ensure that users remain logged in as they navigate through the application.
  • Authenticate Users: Store information about logged-in users to handle authentication and authorization.

How Sessions Work

Session Creation

When a user first visits a Rails application:

  1. Session ID Generation: Rails generates a unique session ID, a long, random string.
  2. Cookie Storage: This session ID is stored in a cookie named _your_app_name_session by default.
  3. Server-side Storage: Rails creates a server-side session storage linked to this ID.

Session Storage Options

Rails provides several options for storing session data:

a. Cookie Store (default)

  • Storage: Session data is stored directly in the cookie.
  • Security: Encrypted and signed to prevent tampering.
  • Limitations: Limited to 4KB of data.
  • Performance: Fastest option as no server-side lookup is needed.

b. Cache Store

  • Storage: Uses Rails cache (e.g., Memcached, Redis).
  • Capacity: Allows larger data storage.
  • Performance: Faster than database storage as it uses in-memory stores.

c. Database Store

  • Storage: Stores session data in a database table.
  • Capacity: Suitable for large data and queryable sessions.
  • Performance: Slower due to database access.

d. Custom Store

  • Flexibility: Implement your own storage mechanism based on specific needs.

Handling Sessions in Rails

For each request:

  1. Reading the Session: Rails reads the session cookie from the request.
  2. Decryption and Verification: For cookie store, it decrypts and verifies the session data.
  3. Accessing Data: The session data is made available via the session hash in controllers and views.
  4. Saving Changes: Any changes to the session are saved at the end of the request cycle.

Using Sessions

Setting Session Data

session[:user_id] = user.id

Reading Session Data

current_user_id = session[:user_id]

Deleting Session Data

session.delete(:user_id)

Clearing Entire Session

reset_session

Session Security

Rails implements several security measures to protect session data:

Encryption

  • Encrypted Data: Session data is encrypted to prevent tampering.
  • Configuration: By default, Rails uses AES-256-GCM for encryption.

Session ID Rotation

  • Prevention: Rotating session IDs helps prevent session fixation attacks.

Secure Flags

  • HTTP-only Cookies: Cookies are set with HttpOnly flag to prevent JavaScript access.
  • Secure Cookies: Set with Secure flag to ensure cookies are only sent over HTTPS.

Expiration

  • Configured Expiry: Sessions can be configured to expire after a set time period.

Example Configuration

In config/initializers/session_store.rb:

Rails.application.config.session_store :cookie_store,
key: '_your_app_session',
expire_after: 30.days

Performance Considerations

  • Cookie-based Sessions: Fastest but limited in size (4KB).
  • Cache-based Sessions: Good balance of speed and capacity.
  • Database Sessions: Slower but offer persistence and the ability to query session data.

Testing with Sessions

Rails provides methods to manipulate sessions in tests:

session[:user_id] = users(:john).id

How Devise Handles Sessions in Rails

Devise is a popular authentication solution for Rails applications that simplifies the process of managing user sessions. It builds upon Rails’ session handling mechanisms and provides additional features and security measures tailored for user authentication.

Session Management with Devise

Devise manages sessions in a Rails application through the following processes:

  1. Session Creation and Destruction:
  • Sign In: When a user signs in using Devise, it authenticates the user’s credentials (e.g., email and password) and stores the user’s ID in the session.
sign_in(user)
  • Sign Out: When a user signs out, Devise removes the user ID from the session and invalidates the session.
sign_out(user)

2. Storing User ID in Session:

  • Devise uses the Rails session to store the authenticated user’s ID. This allows Devise to identify the user across multiple requests.
  • The session key used by Devise is _session_id by default.

3. Session Expiration and Timeout:

  • Devise can automatically expire sessions after a period of inactivity to enhance security. This is achieved through the timeoutable module.
Devise.setup do |config|
config.timeout_in = 30.minutes
end

4. Remember Me:

  • Devise supports a “Remember Me” feature that allows users to stay signed in even after closing their browser. This is done by generating a persistent cookie that stores a token linking to the user.

Using Devise Modules for Session Management

Devise provides several modules that enhance session management:

  • Authenticatable: Handles user authentication and stores the user ID in the session.
  • Timeoutable: Expires sessions after a period of inactivity.
  • Rememberable: Manages the “Remember Me” functionality.
  • Trackable: Tracks sign-in count, timestamps, and IP addresses.

Example of Devise Configuration

In the config/initializers/devise.rb file, you can configure various aspects of Devise's session handling:

Devise.setup do |config|
# Configure session timeout
config.timeout_in = 30.minutes
# Enable "Remember Me" functionality
config.remember_for = 2.weeks
# Set secure flags for cookies
config.rememberable_options = { secure: true, httponly: true }
# Set up other Devise modules as needed
config.omniauth :facebook, 'APP_ID', 'APP_SECRET'
end

Accessing and Modifying Sessions in Devise Controllers

You can access and modify sessions in Devise controllers like any other Rails controller:

class Users::SessionsController < Devise::SessionsController
def create
super do |resource|
# Custom logic after sign in
session[:custom_data] = "some data"
end
end
def destroy
# Custom logic before sign out
session.delete(:custom_data)
super
end
end

Security Considerations

Devise enhances Rails’ session security with additional measures:

  • Secure and HTTP-only Cookies: Ensures that session cookies are only sent over HTTPS and are not accessible via JavaScript.
  • Session Expiry and Invalidation: Automatically expires and invalidates sessions to protect against session hijacking and fixation attacks.
  • Token-based Authentication: Uses tokens for features like “Remember Me” to enhance security further.

Conclusion

Understanding how sessions work in Rails, from creation to security measures, helps in making informed decisions about session management in your application. Properly configured and utilized sessions can greatly enhance the functionality and user experience of your Rails application.

By leveraging the various session storage options and adhering to best practices, you can ensure that your application maintains user state securely and efficiently across multiple requests.

Devise leverages Rails’ session management while adding robust authentication features and security enhancements. By using Devise, you can handle user sessions more effectively, ensuring a secure and seamless authentication experience for your Rails application.

--

--

Bhavyansh @ DiversePixel
Bhavyansh @ DiversePixel

Written by Bhavyansh @ DiversePixel

Hey I write about Tech. Join me as I share my tech learnings and insights. 🚀

No responses yet