【Ruby on Rails】Deviseで本格的な認証機能を実装する

Ruby

こんにちは、かつコーチです。

自前で認証機能を作っていると、パスワードリセットやメール確認、アカウントロックなど、実装すべき機能がどんどん増えていきます。

この記事では、認証gemの定番であるDeviseの導入手順と、実務でよく使う設定を整理します。

has_secure_passwordとの使い分けも合わせて解説するので、どちらを選ぶべきか判断する材料にしてください。

Deviseの導入手順

Gemfileへの追加とインストール

まずはGemfileにDeviseを追加します。

# Gemfile
gem "devise"

追加したらbundle installを実行します。

bundle install

続いてDeviseのジェネレータを実行し、初期設定ファイルを生成します。

rails generate devise:install

このコマンドを実行すると、config/initializers/devise.rbconfig/locales/devise.en.ymlが生成されます。

同時にターミナルへ、default_url_optionsの設定など残タスクの案内が表示されます。

見落とすと後述のエラーにつながるので、必ず全文を読んでおきましょう。

Userモデルの生成

次に、認証対象となるモデルをDeviseのジェネレータで作成します。

rails generate devise User

このコマンドで以下が自動生成されます。

  • app/models/user.rb(Deviseモジュールを含むモデル)
  • db/migrate/xxxx_devise_create_users.rb(マイグレーションファイル)
  • config/routes.rbへのdevise_for :usersの追加

生成されたuser.rbは次のような内容になっています。

# app/models/user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end

マイグレーションを実行してテーブルを作成します。

rails db:migrate

必須の環境設定

Deviseを動かすには、config/environments/development.rbなどにメール送信元URLの設定が必要です。

# config/environments/development.rb
Rails.application.configure do
  config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
end

本番環境(production.rb)にも、実際のドメインで同様の設定を追加してください。

これを忘れると、パスワードリセットメールのリンクが正しく生成されません。

Deviseとhas_secure_passwordの使い分け

実装コストと機能範囲の違い

has_secure_passwordは、Rails標準のbcryptベース認証機能です。

パスワードのハッシュ化と検証だけを提供する、最小限の認証機構(自分でログイン・ログアウトの処理を書く必要がある仕組み)です。

一方Deviseは、以下の機能をモジュール単位で標準搭載しています。

機能has_secure_passwordDevise
パスワードハッシュ化
ログイン・ログアウト自前実装標準搭載
パスワードリセット自前実装:recoverable
メール確認自前実装:confirmable
アカウントロック自前実装:lockable
Remember me自前実装:rememberable

どちらを選ぶべきか

判断軸はシンプルで、要求される機能の広さです。

社内ツールや学習用アプリのように、ログイン機能さえあれば十分なケースではhas_secure_passwordで十分です。

依存gemが少なく、認証フローを完全にコントロールできるメリットがあります。

一方、パスワードリセットやメール確認、アカウントロックなど、実務レベルのセキュリティ要件が求められるサービスではDeviseが有利です。

車輪の再発明を避けられ、実績あるgemに任せることでバグ混入のリスクも減らせます。

私の経験では、MVP開発の初期はhas_secure_passwordで素早く作り、機能要件が固まった段階でDeviseへ移行するケースもよく見かけます。

よくあるつまずきポイント・エラー対処

未ログイン時のリダイレクト設定

Deviseを導入した直後、未ログインユーザーを特定のページへ強制的にログインさせたい場面があります。

❌Before

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
end

このままだと、ログインしていないユーザーでもすべてのアクションにアクセスできてしまいます。

✅After

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :authenticate_user!
end

authenticate_user!はDeviseが提供するヘルパーメソッドです。

未ログイン状態でアクセスすると、自動的にログイン画面へリダイレクトされます。

default_url_options未設定によるエラー

私が初めてDeviseのパスワードリセット機能を試したとき、次のエラーに遭遇しました。

ActionView::Template::Error (Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true)

原因は、前述のdefault_url_optionsをdevelopment環境の設定ファイルに追加し忘れていたことでした。

パスワードリセットメール内のリンクを生成する際、Deviseはホスト名の情報を必要とします。

config/environments/development.rbconfig.action_mailer.default_url_options = { host: "localhost", port: 3000 }を追加したところ、エラーは解消しました。

環境ごとに設定が必要な点を忘れないようにしてください。

まとめ

この記事のポイント

  • Deviseはgem "devise"追加後、rails generate devise:installrails generate devise Userで導入する
  • default_url_optionsの設定漏れは、メールリンク生成時のエラーの原因になりやすい
  • has_secure_passwordは最小構成、Deviseは機能豊富という違いを踏まえて選定する
  • 未ログインユーザーの制御にはauthenticate_user!を使う

次に読むべき記事

  • has_secure_passwordで認証機能を実装する
  • CSRF対策とStrong Parametersでセキュリティを守る

タグ: Ruby on Rails, 上級者向け, 認証

タイトルとURLをコピーしました