Rails 8 Authentication generator: user sign in
Recently DHH merged a PR that adds an authentication generator to Rails.
Currently the generator allows email-password log in for existing users. It does not tackle registrations.
Let’s try it out!
Create a new app using Rails main
branch:
rails new authy -c=tailwind --main
Run the generator & create a user
bin/rails generate authentication
rails db:create db:migrate
rails c
User.create(email_address: "foo@bar", password: "foo@bar")
Create pages that should be accessible with & without authentication:
rails g controller home index dashboard
Now your routes should look like this:
# config/routes.rb
Rails.application.routes.draw do
get "dashboard", to: "home#dashboard"
resource :session, only: %i[new create destroy]
root "home#index"
end
Only authenticated users can visit dashboard:
# app/controllers/home_controller.rb
class HomeController < ApplicationController
# allow users that are not logged in to see #index
+ allow_unauthenticated_access(only: :index)
# make Current.user available on unauthenticated pages
+ before_action :resume_session, only: [:index]
def index
end
def dashboard
end
end
Display sign in/out links:
# app/views/layouts/application.html.erb
<body>
+ <%= link_to 'Home', root_path %>
+ <%= link_to 'Dashboard', dashboard_path %>
+ <% if authenticated? %>
+ <%= Current.user.email_address %>
+ <%= button_to 'Sign out', session_path, method: :delete %>
+ <% else %>
+ <%= link_to 'Sign in', new_session_path %>
+ <% end %>
+ <hr>
<main class="container mx-auto mt-28 px-5 flex flex-col">
<%= yield %>
</main>
</body>
Test the new controller.
For some reason, Current attributes are not available for me in the controller test.
# test/controllers/home_controller_test.rb
require "test_helper"
class HomeControllerTest < ActionDispatch::IntegrationTest
test "should get index" do
get root_url
assert_response :success
end
test "should get dashboard" do
get dashboard_url
assert_redirected_to new_session_url
user = User.create!(email_address: "yaro@example.com", password: "123abc")
post session_url, params: { email_address: 'yaro@example.com', password: '123abc' }
get dashboard_url
assert_response :success
assert_match user.email_address, response.body
# assert_equal user.email_address, Current.user.email_address
delete session_url
assert_redirected_to new_session_url
get dashboard_url
assert_redirected_to new_session_url
# assert_nil Current.session
# assert_nil Current.user
end
end
Fix undefined method 'destroy' for nil:NilClass
when trying to log out:
# app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
- allow_unauthenticated_access
+ allow_unauthenticated_access(only: %i[new create])
Display error message when unauthenticated user requests a page that requires authentication:
# app/controllers/concerns/authentication.rb
def request_authentication
session[:return_to_after_authenticating] = request.url
- redirect_to new_session_url
+ redirect_to new_session_url, alert: "Authenticate to access this page."
end
I think this errors will be fixed soon. It could be a good first PR into rails/rails!
Did you like this article? Did it save you some time?