In an industry where adding a simple login system often means wrestling with gem dependencies and configuration files, Rails has taken a refreshingly contrarian stance: what if authentication could be both secure and simple?
The typical authentication story in web development reads like a cautionary tale: start with a third-party gem, sprinkle in some middleware, juggle configuration files, and pray nothing breaks during the next framework update. It's a complexity tax we've been paying for so long that we've forgotten to question it.
Rails 8 suggests a different path. Let's explore how a single generator command challenges years of authentication complexity.
1. Generate Authentication System
# Generate the authentication system
rails generate authentication
This generates a focused set of files - notably fewer than traditional authentication gems, but that's by design:
# Generated migrations
db/migrate/YYYYMMDDHHMMSS_create_users.rb
db/migrate/YYYYMMDDHHMMSS_create_sessions.rb
# Generated models
app/models/user.rb
app/models/session.rb
app/models/current.rb
# Generated controllers
app/controllers/sessions_controller.rb # Handles sign in/out
app/controllers/passwords_controller.rb # Handles password reset
# Generated views
app/views/passwords/new.html.erb # Password reset request
app/views/passwords/edit.html.erb # Password reset form
# Generated mailers
app/mailers/passwords_mailer.rb
app/views/passwords_mailer/reset.html.erb
app/views/passwords_mailer/reset.text.erb
2. Set Up Landing Page
# Generate home controller for public landing
rails generate controller Home index
# config/routes.rb
Rails.application.routes.draw do
# Authentication routes added
resource :session
resources :passwords, param: :token
# - new_session_path (GET) -> Sign in form
# - session_path (POST) -> Create session (sign in)
# - session_path (DELETE) -> Sign out
# - new_password_path (GET) -> Password reset request
# - edit_password_path (GET) -> Password reset form
# - password_path (PATCH) -> Update password
root "home#index"
# Some user dashboard
resources :dashboard
end
3. Run Migrations
rails db:migrate
This sets up:
- Users table with secure password handling
- Sessions table for managing sign-ins
4. Add User Registration
Rails intentionally leave registration open-ended - because no two applications handle user signup the same way and it makes sense not to include it in the auth generator. Here's a minimal implementation:
# app/controllers/registrations_controller.rb
class RegistrationsController < ApplicationController
allow_unauthenticated_access
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
# Optionally sign in the user after registration
start_new_session_for @user
redirect_to root_path, notice: "Welcome!"
else
render :new, status: :unprocessable_entity
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
Add the routes:
# config/routes.rb
Rails.application.routes.draw do
resources :registrations, only: [:new, :create]
# ... other routes
end
5. Protect Your Controllers
# app/controllers/dashboard_controller.rb
class DashboardController < ApplicationController
before_action :require_authentication
def index
@projects = Current.user.projects
end
end
# app/controllers/home_controller.rb
class HomeController < ApplicationController
allow_unauthenticated_access only: [:index]
def index
# Your public landing page
end
end
Key Features You Get For Free
- Secure password hashing with bcrypt
- Session management with secure tokens
- Automatic session resumption across browser restarts
- Password reset via email
- CSRF protection
- Secure post-authentication redirects
- XSS protection headers
A Note on Design Philosophy
Rails' authentication system exemplifies a crucial architectural principle: sophistication through simplicity. Instead of the kitchen-sink approach, you get:
- Core authentication logic that's secure
- Freedom to implement registration and user management your way
- No framework lock-in for additional features
- Clear separation between authentication and user functionality
This approach acknowledges a truth many frameworks miss: while authentication fundamentals are universal, user management rarely is.
Further Reading
For those interested in diving deeper:
- Rails Authentication from Scratch - If you don't want to use any gems like devise and if you were to create all the views, controllers, models, and mailers to build a simple authentication
- Rails 8 Authentication Deep Dive - Great article to learn a bit more about the rails authentication generator
- Ruby on Rails Guide - Official documentation
Building Your Own
While Rails now provides authentication out of the box, understanding how to build it from scratch remains valuable. The GoRails tutorial walks through implementing similar functionality manually - a great exercise for understanding the security principles at play.
Remember: the best authentication system isn't the one with the most features, but the one that provides security without sacrificing developer productivity or application flexibility.
Top comments (0)