Broken Authentication in Rails
Rails applications commonly use Devise for authentication, but broken auth occurs when before_action :authenticate_user! is missing from controllers, when session cookies are misconfigured, and when password reset flows have timing or token reuse vulnerabilities.
Scan Your Rails AppHow Broken Authentication Manifests in Rails
Broken auth in Rails manifests as: Controllers that forget before_action :authenticate_user! or use skip_before_action too broadly. New actions added to existing controllers often miss auth checks. Devise configurations that allow weak passwords, do not enforce lockout after failed attempts, or have overly long session timeouts. Custom auth flows that do not call reset_session after login, enabling session fixation. API endpoints that accept user IDs as parameters instead of deriving them from the session.
Real-World Impact
A Rails application added a new admin controller action but forgot to add before_action :authenticate_user!. The action was an export endpoint that returned a CSV of all user data. An attacker discovered the unprotected endpoint through directory enumeration and downloaded the entire user database.
Step-by-Step Fix
Apply auth globally with targeted skips
Set auth at ApplicationController level and skip only where needed.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :authenticate_user!
end
# Only skip for specific public actions
class PagesController < ApplicationController
skip_before_action :authenticate_user!, only: [:home, :about, :pricing]
endConfigure Devise security settings
Enable lockout, set password requirements, and configure session timeout.
# config/initializers/devise.rb
Devise.setup do |config|
config.password_length = 10..128
config.lock_strategy = :failed_attempts
config.maximum_attempts = 5
config.unlock_strategy = :time
config.unlock_in = 30.minutes
config.timeout_in = 30.minutes
config.expire_all_remember_me_on_sign_out = true
endRegenerate session on login
Prevent session fixation in custom auth flows.
# For custom auth (Devise handles this automatically)
def create
user = User.find_by(email: params[:email])
if user&.authenticate(params[:password])
reset_session # Prevent session fixation
session[:user_id] = user.id
redirect_to dashboard_path
else
flash.now[:alert] = 'Invalid credentials'
render :new
end
endPrevention Best Practices
1. Apply before_action :authenticate_user! in ApplicationController and skip only for public actions. 2. Configure Devise with strong password requirements, lockout, and session timeout. 3. Call reset_session on login in custom auth flows. 4. Use current_user for identity, never trust params[:user_id]. 5. Test all controller actions for auth enforcement.
How to Test
1. Review controllers for missing before_action :authenticate_user!. 2. Try accessing actions directly via URL without logging in. 3. Check Devise config for password strength and lockout settings. 4. Verify session ID changes after login. 5. Use Vibe App Scanner to detect broken auth in your Rails application.
Frequently Asked Questions
Does Devise prevent all authentication attacks?
Devise handles password hashing, session management, and token generation securely. However, it does not enforce auth on your controllers automatically. You must add before_action :authenticate_user! to protect routes. Devise is a toolkit, not a complete security solution.
How do I add rate limiting to Rails auth?
Devise does not include rate limiting by default. Use the rack-attack gem to add rate limiting to login endpoints. Configure it to block IPs after too many failed login attempts.
Should I use has_secure_password or Devise?
For simple auth needs, has_secure_password with bcrypt is sufficient. For production apps, Devise provides password reset, account confirmation, session management, and lockout features that would take significant effort to build securely from scratch.
Related Security Resources
Is Your Rails App Vulnerable to Broken Authentication?
VAS automatically scans for broken authentication vulnerabilities in Rails applications and provides step-by-step remediation guidance with code examples.
Scans from $5, results in minutes. Get actionable fixes tailored to your Rails stack.