🔐

Rails 8の認証機能を試す

2024/10/03に公開

Rails 8の認証機能を試してみました。
作業内容は以下の記事を参考にしました。

https://medium.com/@azzenabidi/how-to-setup-authentication-in-rails-8-33295a31c356

https://blog.corsego.com/rails-8-authentication

$ rails generate controller Home index dashboard
      create  app/controllers/home_controller.rb
       route  get "home/index"
              get "home/dashboard"
      invoke  erb
      create    app/views/home
      create    app/views/home/index.html.erb
      create    app/views/home/dashboard.html.erb
      invoke  test_unit
      create    test/controllers/home_controller_test.rb
      invoke  helper
      create    app/helpers/home_helper.rb
      invoke    test_unit

config/routes.rbを変更します。

  root to: "home#index"
  get "dashboard", to: "home#dashboard"

app/views/layouts/application.html.erbに上記のリンクを追加します。

  <body>
    <%= link_to 'Home', root_path %>
    <%= link_to 'Dashboard', dashboard_path %>
    <%= yield %>
  </body>

参考記事ではbin/rails generate sessionsとなっていたのですが、このコマンドが存在しなかったため、bin/rails generate authenticationを実行しました。

$ bin/rails generate authentication
      invoke  erb
      create    app/views/passwords/new.html.erb
      create    app/views/passwords/edit.html.erb
      create    app/views/sessions/new.html.erb
      create  app/models/session.rb
      create  app/models/user.rb
      create  app/models/current.rb
      create  app/controllers/sessions_controller.rb
      create  app/controllers/concerns/authentication.rb
      create  app/controllers/passwords_controller.rb
      create  app/mailers/passwords_mailer.rb
      create  app/views/passwords_mailer/reset.html.erb
      create  app/views/passwords_mailer/reset.text.erb
      create  test/mailers/previews/passwords_mailer_preview.rb
        gsub  app/controllers/application_controller.rb
       route  resources :passwords, param: :token
       route  resource :session
        gsub  Gemfile
      bundle  install --quiet
    generate  migration CreateUsers email_address:string!:uniq password_digest:string! --force
       rails  generate migration CreateUsers email_address:string!:uniq password_digest:string! --force 
      invoke  active_record
      create    db/migrate/20241003125109_create_users.rb
    generate  migration CreateSessions user:references ip_address:string user_agent:string --force
       rails  generate migration CreateSessions user:references ip_address:string user_agent:string --force 
      invoke  active_record
      create    db/migrate/20241003125110_create_sessions.rb
$ rails db:migrate

以下のテーブルが追加されました。

  create_table "sessions", force: :cascade do |t|
    t.integer "user_id", null: false
    t.string "ip_address"
    t.string "user_agent"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["user_id"], name: "index_sessions_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "email_address", null: false
    t.string "password_digest", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email_address"], name: "index_users_on_email_address", unique: true
  end

次にapp/controllers/home_controller.rbに以下を追加しました。これを追加することでトップページ以外にアクセスすると認証を求められるようになります。

class HomeController < ApplicationController
  allow_unauthenticated_access only: [:index] # 追加

ユーザーを作成します。

$ rails console
User.create(email_address: "dev@example.com", password: "password")
  SQL (0.1ms)  BEGIN immediate TRANSACTION
  User Create (0.7ms)  INSERT INTO "users" ("email_address", "password_digest", "created_at", "updated_at") VALUES ('dev@example.com', '$2a$12$kpa36pbZtI0StOP0XOwPwuDUMVdgYhE11wKmQo0FtCz4VlkRnF1Ba', '2024-10-03 13:06:54.127436', '2024-10-03 13:06:54.127436') RETURNING "id" 
  TRANSACTION (0.4ms)  COMMIT TRANSACTION
=> 
#<User:0x00000001096b2308
 id: 1,
 email_address: "[FILTERED]",
 password_digest: "[FILTERED]",
 created_at: "2024-10-03 13:06:54.127436000 +0000",
 updated_at: "2024-10-03 13:06:54.127436000 +0000">

続いてapp/controllers/home_controller.rbに以下を追加します。

    <% if authenticated? %>
      <p><%= Current.user.email_address %></p>
      <%= link_to 'Sign out', session_path, method: :delete %>
    <% else %>
      <%= link_to 'Sign in', new_session_path %>
    <% end %>

上記でログインとログアウトの動作を確認することができました。

PRでDHHが2FAなどは期待しないで欲しいという様な話をしているので、用途によってはdeviseや他の認証サービスのほうが向いているかもしれません。

https://github.com/rails/rails/pull/52328

Discussion