Durante más de una década, Devise fue la respuesta automática a «¿cómo añado autenticación a mi app Rails?». Es una gema madura, bien mantenida y con decenas de funcionalidades. Pero también es una caja negra: genera código que muchos desarrolladores no entienden del todo, tiene su propio sistema de vistas, sus propios helpers y una curva de aprendizaje propia. Rails 8 trae una alternativa nativa con el generator de autenticación.
El generator de autenticación de Rails 8
Un solo comando genera el esqueleto básico de autenticación:
rails generate authentication
Esto crea:
- app/models/user.rb y app/models/session.rb: los modelos de usuario y sesión.
- app/controllers/sessions_controller.rb: login y logout.
- app/controllers/passwords_controller.rb: recuperación de contraseña.
- app/controllers/concerns/authentication.rb: el concern con los helpers.
- Vistas: formularios de login y recuperación de contraseña.
- Migraciones: tablas
usersysessions. - Mailer:
PasswordsMailerpara enviar el email de recuperación.
Qué genera el modelo User
# app/models/user.rb (generado)
class User < ApplicationRecord
has_secure_password
has_many :sessions, dependent: :destroy
normalizes :email_address, with: -> { _1.strip.downcase }
end
has_secure_password es un método de ActiveRecord que lleva en Rails desde la versión 3.1. Usa BCrypt para hashear la contraseña y añade automáticamente los métodos authenticate, password= y password_confirmation=. Solo necesita que la tabla tenga una columna password_digest.
normalizes :email_address es una funcionalidad de Rails 7.1 que normaliza el email automáticamente antes de guardarlo: elimina espacios y convierte a minúsculas.
El modelo Session
# app/models/session.rb (generado)
class Session < ApplicationRecord
belongs_to :user
end
# Migración correspondiente
class CreateSessions < ActiveRecord::Migration[8.0]
def change
create_table :sessions do |t|
t.references :user, null: false, foreign_key: true
t.string :ip_address
t.string :user_agent
t.timestamps
end
end
end
Cada login crea una fila en sessions. El token de sesión se guarda en una cookie signed. Esto permite, entre otras cosas, ver sesiones activas o invalidarlas individualmente (cerrar sesión en un dispositivo concreto).
El concern Authentication
# app/controllers/concerns/authentication.rb (generado, simplificado)
module Authentication
extend ActiveSupport::Concern
included do
before_action :require_authentication
helper_method :authenticated?
end
private
def authenticated?
Current.session.present?
end
def require_authentication
resume_session || request_authentication
end
def resume_session
Current.session ||= find_session_by_cookie
end
def find_session_by_cookie
Session.find_by(id: cookies.signed[:session_id])
end
def request_authentication
session[:return_to_after_authenticating] = request.url
redirect_to new_session_url
end
end
# En ApplicationController
class ApplicationController < ActionController::Base
include Authentication
end
Para las acciones que no requieren autenticación (la página de inicio pública, el formulario de login), se usa allow_unauthenticated_access:
class SessionsController < ApplicationController
allow_unauthenticated_access only: [:new, :create]
def new; end
def create
if user = User.authenticate_by(email_address: params[:email_address],
password: params[:password])
start_new_session_for user
redirect_to after_authentication_url
else
redirect_to new_session_url, alert: "Email o contraseña incorrectos"
end
end
def destroy
terminate_session
redirect_to new_session_url
end
end
Lo que no incluye el generator
El generator de Rails 8 es deliberadamente minimalista. No incluye:
- Registro de usuarios: tienes que crear el formulario de registro y el controlador tú mismo.
- Confirmación de email: no hay flujo de verificación de email al registrarse.
- Autenticación social: Google, GitHub, etc. requieren OmniAuth u otra solución.
- OTP / 2FA: no hay soporte de dos factores.
- Magic links: no incluido por defecto.
- Roles y permisos: el generator no toca autorización, solo autenticación.
Para aplicaciones con estos requisitos, Devise sigue siendo una opción sólida. Rodauth es otra alternativa que merece atención: es más explícita en su funcionamiento que Devise y tiene soporte nativo para OTP, magic links y WebAuthn.
Cuándo usar el generator nativo
El generator de Rails 8 va bien para:
- Aplicaciones internas donde controlas los usuarios manualmente.
- APIs donde la autenticación es simple (email + password, sin OAuth).
- Proyectos educativos donde quieres entender cómo funciona la autenticación desde dentro.
- Proyectos donde Devise era excesivo y solo necesitabas lo básico.
La ventaja principal sobre Devise es que el código generado es tuyo: puedes leerlo, modificarlo y entenderlo sin bucear en las entrañas de una gema. Si algo falla, el stack trace lleva directamente a tu código.
Si te interesa ver la autenticación en otro framework backend, el artículo sobre PHP 8.4 tiene contexto sobre cómo el ecosistema PHP gestiona la seguridad en aplicaciones web modernas.
Imagen: Pexels / Miguel Á. Padriñán
