CodeKitchen

Rails認証gem「devise」徹底ガイド

rails ruby device

1. はじめに

Railsでユーザー認証を実装する際に、真っ先に候補に挙がるのが「devise」というgemではないでしょうか。deviseは、Railsアプリケーションにユーザー認証機能を追加するための強力で柔軟なソリューションです。

deviceとは何か

deviseは、Railsアプリケーションにユーザー認証を追加するためのgemです。ユーザー登録、ログイン、ログアウト、パスワードリセット、メール確認など、認証に関連する一連の機能を提供します。deviseは、Railsのコーディング規約に沿って設計されているため、Railsの開発者にとって使いやすく、簡単に導入することができます。

deviceを使うメリット

deviseを使うメリットは以下の通りです。

  1. 実装の簡略化

    • deviseは、認証に関連する複雑な処理を抽象化し、シンプルなAPIを提供します。これにより、開発者は認証機能の実装に費やす時間を大幅に削減できます。
  2. 安全性の向上

    • deviseは、セキュリティの観点から設計されており、一般的な脆弱性への対策が施されています。適切な設定を行うことで、アプリケーションのセキュリティを向上させることができます。
  3. 柔軟性と拡張性

    • deviseは、柔軟な設定オプションと豊富な拡張機能を提供します。これにより、アプリケーションの要件に合わせて認証機能をカスタマイズし、拡張することができます。

認証と認可の違い

認証(Authentication)と認可(Authorization)は、しばしば混同されがちな概念です。簡単に説明すると、以下のような違いがあります。

  • 認証(Authentication)

    • ユーザーが主張する身元を確認するプロセス。
    • 「ユーザーが本人であることを確認する」ことが目的。
    • devise gemは、主に認証を担当する。
  • 認可(Authorization)

    • ユーザーに特定のリソースへのアクセス権限を付与するプロセス。
    • 「ユーザーにどの機能を使う権限があるかを決定する」ことが目的。
    • pundit, cancancanなどの認可用のgemと組み合わせて使われることが多い。

認証と認可は、セキュリティの観点から両方を適切に実装する必要があります。まずは認証を実装し、その後、認可を追加するのが一般的な流れです。

次の章では、実際にdeviseをRailsアプリケーションに導入する方法について解説します。

2. deviceのインストールと設定

この章では、Railsアプリケーションへのdeviseのインストールと初期設定の方法について説明します。

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

まず、Gemfileに以下の行を追加します。

gem 'devise'

次に、ターミナルで以下のコマンドを実行し、deviseをインストールします。

bundle install

devise関連ファイルの生成

deviseに必要なファイルを生成するために、以下のコマンドを実行します。

rails generate devise:install

このコマンドにより、devise用の設定ファイルや、環境ごとの設定を追加するための手順が表示されます。表示された手順に従って、必要な設定を行います。

モデルへのdeviseの追加

ユーザー認証を行うモデル(通常はUserモデル)に、deviseの機能を追加します。以下のコマンドを実行します。

rails generate devise User

このコマンドにより、Userモデルにdeviseに関連するカラムが追加され、config/routes.rbにdeviseのルーティングが追加されます。

生成されたマイグレーションファイルを確認し、必要に応じてカラムを追加したり、カスタマイズしたりします。その後、以下のコマンドでマイグレーションを実行します。

rails db:migrate

ルーティングの設定

config/routes.rbを開き、以下のようにdeviseのルーティングが追加されていることを確認します。

Rails.application.routes.draw do
  devise_for :users
  # ... 他のルーティング
end

この設定により、ユーザー登録、ログイン、ログアウトなどのためのルーティングが自動的に追加されます。

devise設定ファイルの解説

config/initializers/devise.rbは、deviseの設定を行うためのファイルです。このファイルには、多数の設定項目がコメントアウトされた状態で含まれています。必要に応じて、コメントを外して設定を変更することができます。

よく利用される設定項目には、以下のようなものがあります。

  • config.mailer_sender: deviseが送信するメールのFromアドレスを設定します。
  • config.authentication_keys: ログインに使用するカラムを指定します。
  • config.password_length: パスワードの最小文字数と最大文字数を設定します。
  • config.stretches: パスワードのハッシュ化に使用するストレッチ回数を設定します。

これらの設定を適切に行うことで、アプリケーションの要件に合わせてdeviseの動作をカスタマイズすることができます。

次の章では、deviseが提供する主要な機能について、具体的な使い方を説明します。

3. deviceの機能と使い方

この章では、deviseが提供する主要な機能について、具体的な使い方を説明します。サンプルコードやシーケンス図を交えながら、各機能の実装方法を詳しく解説します。

ユーザー登録

ユーザー登録は、新しいユーザーがアプリケーションを利用するために必要な情報を入力し、アカウントを作成するプロセスです。

サンプルコード

app/views/devise/registrations/new.html.erbにユーザー登録用のビューが用意されています。このファイルを編集することで、ユーザー登録フォームをカスタマイズできます。

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

登録フローのシーケンス図

DatabaseRailsBrowserUserDatabaseRailsBrowserUseralt[成功][失敗]アクセスGET /users/sign_up登録フォームを表示フォームに入力POST /usersユーザーを作成作成結果を返す登録完了ページを表示登録フォームを再表示

ストロングパラメータの設定

ユーザー登録時に受け取るパラメータを制限するために、ストロングパラメータを設定します。app/controllers/application_controller.rbに以下のように記述します。

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
  end
end

この例では、ユーザー登録時に:name属性を許可しています。

ログイン・ログアウト

ログインは、登録済みのユーザーがアプリケーションにアクセスするためのプロセスです。ログアウトは、ユーザーがアプリケーションからサインアウトするプロセスです。

サンプルコード

app/views/devise/sessions/new.html.erbにログイン用のビューが用意されています。このファイルを編集することで、ログインフォームをカスタマイズできます。

<h2>Log in</h2>

<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <div class="field">
    <%= f.label :password %><br />
    <%= f.password_field :password, autocomplete: "current-password" %>
  </div>

  <% if devise_mapping.rememberable? %>
    <div class="field">
      <%= f.check_box :remember_me %>
      <%= f.label :remember_me %>
    </div>
  <% end %>

  <div class="actions">
    <%= f.submit "Log in" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

ログインフローのシーケンス図

DatabaseRailsBrowserUserDatabaseRailsBrowserUseralt[成功][失敗]アクセスGET /users/sign_inログインフォームを表示フォームに入力POST /users/sign_inユーザーを検索検索結果を返すログイン後のページを表示ログインフォームを再表示

Remember me機能の説明

Remember me機能は、ユーザーがログイン状態を維持できるようにするための機能です。ログインフォームでRemember meのチェックボックスにチェックを入れてログインすると、ユーザーのブラウザにクッキーが保存され、次回以降のアクセス時にもログイン状態が維持されます。

この機能を有効にするには、config/initializers/devise.rbで以下の設定を行います。

config.remember_for = 2.weeks

この例では、Remember me機能でログイン状態を2週間維持するように設定しています。

次の章では、deviseのカスタマイズ方法について説明します。

4. deviceのカスタマイズ

この章では、deviseの機能をアプリケーションの要件に合わせてカスタマイズする方法について説明します。コントローラー、ビュー、モデルのカスタマイズ方法を具体的に解説します。

コントローラーのカスタマイズ

devise_controllerの使用

deviseのコントローラーをカスタマイズするには、devise_controllerメソッドを使用します。このメソッドを使うことで、deviseのコントローラーを継承したカスタムコントローラーを作成できます。

class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]

  protected

  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
  end
end

この例では、Users::RegistrationsControllerを作成し、Devise::RegistrationsControllerを継承しています。configure_sign_up_paramsメソッドを定義し、ユーザー登録時に:name属性を許可しています。

コントローラーの継承とオーバーライド

deviseのコントローラーの動作をカスタマイズするには、対応するアクションをオーバーライドします。

class Users::SessionsController < Devise::SessionsController
  def create
    super do |resource|
      # ログイン後の処理を追加
    end
  end
end

この例では、Users::SessionsControllerを作成し、Devise::SessionsControllerを継承しています。createアクションをオーバーライドし、ログイン後の処理を追加しています。

ビューのカスタマイズ

devise_controllableの使用

deviseのビューをカスタマイズするには、devise_controllableメソッドを使用します。このメソッドを使うことで、deviseのビューを生成するためのコマンドを実行できます。

rails generate devise:views users

このコマンドを実行すると、app/views/users/ディレクトリにdeviseのビューファイルが生成されます。

ビューの生成とカスタマイズ

生成されたビューファイルを編集することで、deviseのビューをカスタマイズできます。例えば、app/views/users/registrations/new.html.erbを編集することで、ユーザー登録ページをカスタマイズできます。

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= render "users/shared/error_messages", resource: resource %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name, autofocus: true %>
  </div>

  <!-- 他のフィールド -->

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "users/shared/links" %>

この例では、ユーザー登録ページに:name属性の入力フィールドを追加しています。

モデルのカスタマイズ

バリデーションの追加

deviseで認証に使用するモデルにバリデーションを追加することで、ユーザー登録時のデータ検証をカスタマイズできます。

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  validates :name, presence: true
end

この例では、Userモデルに:name属性の存在チェックを追加しています。

コールバックの利用

deviseでは、認証プロセスの各段階でコールバックを利用できます。コールバックを使うことで、認証前後の処理を追加できます。

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  after_create :send_welcome_email

  private

  def send_welcome_email
    # ウェルカムメールを送信する処理
  end
end

この例では、Userモデルにafter_createコールバックを追加し、ユーザー登録後にウェルカムメールを送信する処理を実装しています。

次の章では、複数のユーザー種類に対応する方法について説明します。

5. 複数のユーザー種類への対応

アプリケーションによっては、複数のユーザー種類(例: 一般ユーザーと管理者)を扱う必要がある場合があります。この章では、複数のユーザー種類に対応する方法について説明します。

複数のモデルでdeviseを使う方法

複数のユーザー種類に対応するために、それぞれのユーザー種類に対応するモデルを作成します。各モデルに対してdeviseを設定します。

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

# app/models/admin.rb
class Admin < ApplicationRecord
  devise :database_authenticatable, :rememberable, :validatable
end

この例では、UserモデルとAdminモデルを作成し、それぞれにdeviseを設定しています。

モデル毎のルーティング設定(devise_scope)

各モデルに対応するdeviseのルーティングを設定するために、devise_scopeを使用します。

# config/routes.rb
Rails.application.routes.draw do
  devise_for :users
  devise_for :admins, skip: :registrations

  devise_scope :admin do
    get 'admins/edit', to: 'admins/registrations#edit', as: 'edit_admin_registration'
    put 'admins', to: 'admins/registrations#update', as: 'admin_registration'
  end
end

この例では、UserモデルとAdminモデルに対してdeviseのルーティングを設定しています。Adminモデルでは、登録機能をスキップし、編集機能のみを有効にしています。

モデル毎のコントローラー・ビューの作成

各モデルに対応するコントローラーとビューを作成します。

rails generate devise:controllers users
rails generate devise:controllers admins
rails generate devise:views users
rails generate devise:views admins

これらのコマンドを実行すると、各モデルに対応するコントローラーとビューが生成されます。生成されたファイルを編集することで、各ユーザー種類に固有の機能を実装できます。

次の章では、deviseの拡張機能について説明します。

6. deviceの拡張機能

deviseは、認証に関連する様々な拡張機能を提供しています。この章では、代表的な拡張機能について説明します。

Omniauth(外部認証)との連携

OmniAuthは、外部サービス(Google、Facebook、Twitterなど)を利用した認証を実現するためのgemです。deviseとOmniAuthを連携させることで、外部サービスを利用したユーザー認証を簡単に実装できます。

OmniAuthの設定

まず、Gemfileに必要なgemを追加します。

gem 'omniauth-google-oauth2'
gem 'omniauth-facebook'
gem 'omniauth-twitter'

次に、config/initializers/devise.rbにOmniAuthの設定を追加します。

config.omniauth :google_oauth2, 'GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET', scope: 'email'
config.omniauth :facebook, 'FACEBOOK_APP_ID', 'FACEBOOK_APP_SECRET'
config.omniauth :twitter, 'TWITTER_API_KEY', 'TWITTER_API_SECRET'

各サービスのクライアントIDとシークレットを設定します。

コールバック処理の実装

OmniAuthのコールバック処理を実装するために、Users::OmniauthCallbacksControllerを作成します。

# app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google_oauth2
    # Googleアカウントを利用したログイン処理を実装
  end

  def facebook
    # Facebookアカウントを利用したログイン処理を実装
  end

  def twitter
    # Twitterアカウントを利用したログイン処理を実装
  end
end

各サービスからのコールバックに対応するアクションを定義し、必要な処理を実装します。

Confirmable(メール確認)の設定

Confirmableは、ユーザー登録時にメールアドレスの確認を行うための機能です。

Confirmableの有効化

Userモデルに:confirmableを追加します。

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :confirmable
end

マイグレーションファイルに:confirmation_token:confirmed_at:confirmation_sent_atカラムを追加します。

add_column :users, :confirmation_token, :string
add_column :users, :confirmed_at, :datetime
add_column :users, :confirmation_sent_at, :datetime
add_index :users, :confirmation_token, unique: true

メール確認フローの解説

  1. ユーザーがサインアップすると、確認メールが送信される
  2. ユーザーは、メールに記載された確認リンクをクリックする
  3. 確認リンクからUsers::ConfirmationsController#showアクションが呼び出される
  4. ユーザーのconfirmed_at属性が更新され、メールアドレスが確認済みになる

Lockable(アカウントロック)の設定

Lockableは、一定回数のログイン失敗によるアカウントのロックを行うための機能です。

Lockableの有効化

Userモデルに:lockableを追加します。

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :lockable
end

マイグレーションファイルに:failed_attempts:locked_atカラムを追加します。

add_column :users, :failed_attempts, :integer, default: 0
add_column :users, :locked_at, :datetime

ロック解除方法の解説

アカウントがロックされた場合、以下の方法でロックを解除できます。

  1. 一定時間経過後に自動的にロックが解除される(デフォルトでは1時間)
  2. ユーザーが手動でロック解除のリクエストを送信する
    • Users::UnlocksController#newアクションでロック解除リクエストのフォームを表示
    • Users::UnlocksController#createアクションでロック解除メールを送信
    • ユーザーがロック解除メールのリンクをクリックすることでアカウントがロック解除される

二要素認証の実装

二要素認証は、パスワードに加えて別の認証方法を組み合わせることで、セキュリティを強化する手法です。

gem ‘devise-two-factor’の利用

devise-two-factorgemを使用することで、deviseに二要素認証を追加できます。

gem 'devise-two-factor'

Userモデルに:two_factor_authenticatableを追加します。

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :two_factor_authenticatable
end

二要素認証フローの解説

  1. ユーザーがログインすると、パスワードの認証が行われる
  2. パスワードの認証が成功すると、二要素認証コードの入力が求められる
  3. ユーザーは、事前に設定した二要素認証デバイス(Google Authenticatorなど)から認証コードを取得する
  4. ユーザーが認証コードを入力し、認証が成功するとログインが完了する

次の章では、RSpecを使ったdeviseのテストについて説明します。

7. RSpecを使ったdeviseのテスト

アプリケーションの品質を維持するために、deviseの機能に対するテストを書くことが重要です。この章では、RSpecを使ってdeviseのコントローラーとモデル、およびフィーチャースペックのテストを書く方法について説明します。

コントローラーのテスト

deviseのコントローラーをテストするために、devisedevise_controllerをテストに含める必要があります。

# spec/controllers/users/registrations_controller_spec.rb
require 'rails_helper'

RSpec.describe Users::RegistrationsController, type: :controller do
  before do
    @request.env["devise.mapping"] = Devise.mappings[:user]
  end

  describe 'POST #create' do
    context 'パラメータが有効な場合' do
      it 'ユーザーが作成される' do
        expect {
          post :create, params: { user: attributes_for(:user) }
        }.to change(User, :count).by(1)
      end
    end

    context 'パラメータが無効な場合' do
      it 'ユーザーが作成されない' do
        expect {
          post :create, params: { user: attributes_for(:user, email: '') }
        }.not_to change(User, :count)
      end
    end
  end
end

この例では、Users::RegistrationsControllercreateアクションをテストしています。有効なパラメータが渡された場合にユーザーが作成されること、無効なパラメータが渡された場合にユーザーが作成されないことをテストしています。

モデルのテスト

deviseのモデルに追加したバリデーションやコールバックをテストします。

# spec/models/user_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
  describe 'バリデーション' do
    it 'メールアドレスが必須であること' do
      user = build(:user, email: '')
      expect(user).not_to be_valid
    end

    it 'パスワードが必須であること' do
      user = build(:user, password: '')
      expect(user).not_to be_valid
    end
  end

  describe 'コールバック' do
    it 'ユーザー作成後にウェルカムメールが送信されること' do
      expect {
        create(:user)
      }.to change { ActionMailer::Base.deliveries.count }.by(1)
    end
  end
end

この例では、Userモデルのバリデーションとコールバックをテストしています。メールアドレスとパスワードが必須であること、ユーザー作成後にウェルカムメールが送信されることをテストしています。

フィーチャースペックの作成

フィーチャースペックを使ってdeviseの機能を統合的にテストします。

# spec/features/user_registration_spec.rb
require 'rails_helper'

RSpec.feature 'ユーザー登録', type: :feature do
  scenario 'ユーザーが新規登録する' do
    visit new_user_registration_path

    fill_in 'Email', with: '[email protected]'
    fill_in 'Password', with: 'password'
    fill_in 'Password confirmation', with: 'password'
    click_button 'Sign up'

    expect(page).to have_content 'Welcome! You have signed up successfully.'
  end
end

この例では、ユーザー登録のフィーチャースペックを書いています。ユーザー登録ページを訪問し、フォームに必要な情報を入力して送信すると、ユーザー登録が成功することをテストしています。

同様に、ログインやパスワードリセットなどの機能に対するフィーチャースペックを書くことで、deviseの機能が期待通りに動作することを確認できます。

8. まとめ

  • deviseは、Railsアプリケーションにユーザー認証機能を追加するための強力で柔軟なソリューションです。
  • deviseのインストールと初期設定を行うことで、すぐにユーザー認証機能を利用できます。
  • deviseの各機能(ユーザー登録、ログイン・ログアウト、パスワードリセット、メール確認など)の使い方を理解することが重要です。
  • コントローラー、ビュー、モデルをカスタマイズすることで、アプリケーションの要件に合わせてdeviseの動作を変更できます。
  • 複数のユーザー種類に対応する場合は、それぞれのモデルに対してdeviseを設定し、ルーティングやコントローラー、ビューを適切に設定する必要があります。
  • OmniAuthやConfirmable、Lockableなどの拡張機能を利用することで、より高度なユーザー認証機能を実現できます。
  • RSpecを使ってdeviseのコントローラーやモデル、フィーチャースペックのテストを書くことで、アプリケーションの品質を維持できます。
  • ユーザー認証は、アプリケーションのセキュリティにとって非常に重要な機能です。適切に実装し、定期的にテストを行うことが求められます。

deviseは、Railsアプリケーションにユーザー認証機能を追加するための強力なツールです。この記事で説明した内容を理解し、適用することで、セキュアで使いやすいユーザー認証機能を実現できるでしょう。

以上が、Railsのdeviseについての詳細な解説記事のアウトラインとサンプルコードです。実際の記事では、各章の内容をさらに詳しく説明し、具体的なコードやイメージを交えながら、初心者にも理解しやすい文章で書くことが重要です。また、deviseの公式ドキュメントやその他の関連資料へのリンクを提供することで、読者がより深く学ぶことができるようにするとよいでしょう。

logo

Web Developer。パフォーマンス改善、データ分析基盤、生成AIに興味があり。Next.js, Terraform, AWS, Rails, Pythonを中心に開発スキルを磨いています。技術に関して幅広く投稿していきます。