14
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Keisuke Death MarchAdvent Calendar 2023

Day 12

【Rails・Next.js】devise-token-authによるログイン認証 Part1

Posted at

はじめに

Rails7Next.js13環境での、devise-token-authによるログイン認証について手順について説明します。
今回はPart1ということで、devise-token-authの導入までをまとめてみました。

開発環境

  • Ruby on Rails APIモード 7.0.8
  • Next.js 13.4
  • Docker
  • MySQL

devise-token-authとは

Rails APIモードにおいて、認証機能を持ったモデルを実装できるgemです。

devise-token-authの初期設定

Gemfile
 gem "devise"
 gem "devise-i18n"
 gem "devise_token_auth"

deviseをインストールします。

rails g devise:install

Userモデルをdevise_token_authに用いるモデルとして登録します。

rails g devise_token_auth:install User auth
rails db:migrate

usersテーブルが正常に作成されていることを確認します。

schema.rb
ActiveRecord::Schema[7.0].define(version: 2023_12_12_071155) do
  create_table "users", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
    t.string "provider", default: "email", null: false
    t.string "uid", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.boolean "allow_password_change", default: false
    t.datetime "remember_created_at"
    t.string "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string "unconfirmed_email"
    t.string "name"
    t.string "nickname"
    t.string "image"
    t.string "email"
    t.text "tokens"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
    t.index ["uid", "provider"], name: "index_users_on_uid_and_provider", unique: true
  end

end

次にdevise-token-auth用のルーティングを追加します。

routes.rb
  Rails.application.routes.draw do
    namespace :api do
      namespace :v1 do
        get "health_check", to: "health_check#index"
        mount_devise_token_auth_for "User", at: "auth"
      end
    end
  end

メール認証への対応

今回はletter_opener_webを用いたメール認証をする為、作成されているモデルに対して:confirmableオプションを追加します。

app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable
  include DeviseTokenAuth::Concerns::User
end

DisabledSessionErrorの回避

Rails7系の場合、認証時にActionDispatch::Request::Session::DisabledSessionErrorが発生してしまいます。

これは、APIのようにセッションを使用しない場合には、セッションへのアクセスがあるとエラーを発生させる仕組みがRails7から備わったことによるエラーです。

deviseを使った場合、内部的にセッションにアクセスしている為、該当のエラーが発生してしまいます。

エラー回避するために、こちらのissueを参考に設定を行います。

pp/controllers/concerns/devise_hack_fake_session.rb
module DeviseHackFakeSession
  extend ActiveSupport::Concern

  class FakeSession < Hash
    def enabled?
      false
    end

    def destroy
    end
  end

  included do
    before_action :set_fake_session

    private

      def set_fake_session
        if Rails.configuration.respond_to?(:api_only) && Rails.configuration.api_only
          request.env["rack.session"] ||= ::DeviseHackFakeSession::FakeSession.new
        end
      end
  end
end

concernsにモジュールを作成したら、application_controller.rbincludeします。

app/controllers/application_controller.rb
  class ApplicationController < ActionController::API
    include DeviseTokenAuth::Concerns::SetUserByToken
    include DeviseHackFakeSession
  end

おわりに

Part1はここまでです。お疲れ様でした。

14
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?