2
3

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 3 years have passed since last update.

devise_token_authインストール後、deviseのconfirmableでメール認証機能を追加実装する

Last updated at Posted at 2021-05-25

はじめに

devise_token_authをインストールしている状態で、後からdeviseのメール認証機能を追加実装してみたところ、
詰まったポイントがあったので認証APIの実装方法と一緒に備忘録として残します。

※大前提として、今回詰まったことはdevise_token_authをインストールする前にrails g devise:installしておけば発生しない問題でした。。。
最初から実装する場合は
rails g devise:installrails g devise_token_auth:install User auth
の順でコマンドを実行すれば解決するようです。
ただ今回は学習も兼ねて手動で解決したのであえて、再現する形で解決方法を残します。

前提

devise_token_authで認証機能を実装後、後からdeviseのメール認証機能を追加で実装したい。

詰まったこと

deviseを用いてメール認証機能を実装しようとしたが、後からrails g devise:installが実行できず、
メール認証に必要な設定ファイルが足りていなかった。

devisedevise_token_authの両方を用いる場合は
rails g devise:installrails g devise_token_auth:install User auth
の順でコマンドを実行する必要があった。
(後からrails g devise:installコマンドを実行するとエラーとなる)

対策

rails g devise:installで作成されるファイルを確認し、メール認証に必要なものを手動で作成し編集する。

環境

  • Rubyバージョン 2.7.1
  • Rails 6.1.3

実装の流れ

1.Rails(APIモード)でプロジェクトを作成
2.devise_token_authで認証周りの実装
3.confirmableでメール認証機能の追加
4.Action Mailerの設定
5.deviseの設定ファイルを手動で作成  ←今回の詰まったポイント
6.動作確認

1.Rails(APIモード)でプロジェクトを作成

APIモードで新規プロジェクトを作成。

$ rails new test_api --api

gemのインストール

Gemfile
gem 'devise'
gem 'devise_token_auth'
gem 'rack-cors'

Gemfileに追記後、bundle installする。

$ bundle install 

データベースを作成

rails db:create

2.devise_token_authで認証周りの実装

devise_token_authのインストール。
※正しくは先にdeviseのインストールをすべきですが、今回は後から追加する場合の実装方法を再現するため、あえてdevise_token_authのインストールを先に実行しています。

$ rails g devise_token_auth:install User auth

devise_token_auth_create_users.rbファイルの修正

rails g devise_token_auth:install User authコマンドで作成されたdevise_token_auth_create_users.rbファイルを下記のように修正。
後からメール確認の設定を追加する想定のため、現時点ではConfimableの設定箇所をコメントアウト。

db/migrate/20210324032859_devise_token_auth_create_users.rb
class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table(:users) do |t|
      ## Required
      t.string :provider, null: false, default: 'email'
      t.string :uid, null: false, default: ''

      ## Database authenticatable
      t.string :encrypted_password, null: false, default: ''

      ## Recoverable
      t.string :reset_password_token
      t.datetime :reset_password_sent_at
      t.boolean :allow_password_change, default: false

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string :current_sign_in_ip
      t.string :last_sign_in_ip

      # 下記をコメントアウト
      # Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at

      ## User Info
      t.string :name
      t.string :nickname
      t.string :image
      t.string :email

      ## Tokens
      t.text :tokens

      t.timestamps
    end

    add_index :users, :email, unique: true
    add_index :users, %i[uid provider], unique: true
    add_index :users, :reset_password_token, unique: true
    
    # 下記をコメントアウト
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

user.rbの修正

同じく作成されたuser.rbの内容を修正。
ここでもconfirmableの設定は一旦除外しておきます。

app/models/user.rb
# frozen_string_literal: true

class User < ActiveRecord::Base
  extend Devise::Models

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable,
         :registerable,
         :recoverable,
         :rememberable,
         :trackable,
         :validatable
  include DeviseTokenAuth::Concerns::User
end

migrateコマンドで、usersテーブルを作成。

$ rails db:migrate

devise_token_auth.rbの修正

devise_token_auth.rbの下記の設定を変更。

config/initializers/devise_token_auth.rb

config.change_headers_on_each_request = false # コメントアウトを外してfalseに変更

config.token_lifespan = 2.weeks # コメントアウトを外す

# コメントアウトを外す
config.headers_names = {:'access-token' => 'access-token',
                        :'client' => 'client',
                        :'expiry' => 'expiry',
                        :'uid' => 'uid',
                        :'token-type' => 'token-type' }

cors.rbの設定

cors.rbの設定。

config/initializers/cors.rb
# Be sure to restart your server when you modify this file.

# Avoid CORS issues when API is called from the frontend app.
# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.

# Read more: https://github.com/cyu/rack-cors

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'http://localhost:3000' #アクセス元のoriginを設定

    resource '*',
             headers: :any,
             expose: %w[access-token uid client], # トークンの受け渡し用に追加
             methods: %i[get post put patch delete options head]
  end
end

Controllerを作成

$ rails g controller auth/registrations

auth/registrations_controller.rbの修正

auth/registrations_controller.rb
module Auth
  class RegistrationsController < DeviseTokenAuth::RegistrationsController
    private

    def sign_up_params
      params.permit(:name, :email, :password, :password_confirmation)
    end

    def account_update_params
      params.permit(:name, :email)
    end
  end
end

ルートの設定

config/routes.rb
Rails.application.routes.draw do
  mount_devise_token_auth_for 'User', at: 'auth', controllers: {
    registrations: 'auth/registrations'
  }
end

3.confirmableでメール認証機能の追加

ここまででdevise_token_authを用いて認証機能の実装が完了しました。
この状態からメール認証機能の実装をしていきます。

confirmableの有効化

user.rbdevise_token_auth_create_users.rbファイルを修正し、confirmableを有効にする。

app/models/user.rb
# frozen_string_literal: true

class User < ActiveRecord::Base
  extend Devise::Models

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable,
         :registerable,
         :recoverable,
         :rememberable,
         :trackable,
         :validatable,
         :confirmable #追記
  include DeviseTokenAuth::Concerns::User
end

db/migrate/20210324032859_devise_token_auth_create_users.rb
class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[6.1]
  def change
    create_table(:users) do |t|
      ## Required
      t.string :provider, null: false, default: 'email'
      t.string :uid, null: false, default: ''

      ## Database authenticatable
      t.string :encrypted_password, null: false, default: ''

      ## Recoverable
      t.string :reset_password_token
      t.datetime :reset_password_sent_at
      t.boolean :allow_password_change, default: false

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string :current_sign_in_ip
      t.string :last_sign_in_ip

      #  下記のコメントアウトを外す
      # Confirmable
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at

      ## User Info
      t.string :name
      t.string :nickname
      t.string :image
      t.string :email

      ## Tokens
      t.text :tokens

      t.timestamps
    end

    add_index :users, :email, unique: true
    add_index :users, %i[uid provider], unique: true
    add_index :users, :reset_password_token, unique: true
    add_index :users, :confirmation_token,   unique: true # コメントアウトを外す
    # add_index :users, :unlock_token,         unique: true
  end
end


4.Action Mailerの設定

メール送信用のaction mailerの設定(Gmail用の設定)

dotenv-railsのインストール

メールアドレスなど繰り返し使用する値などは外だしした方がいいのでdotenv-railsGemをインストール。

Gemfile
group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'dotenv-rails' # 追加
end
$ bundle install

メールのアプリパスワードを取得

Action MailerでGmailを利用するにはアプリパスワードが必要なため取得する。
(ご自身のGmailアカウントの設定画面にて2段階認証を行うことで、アプリパスワードが取得できます。)

.envファイルの設定

.envファイルを作成し、下記内容で保存する。

.env
EMAIL_ADDRESS=<ご自身のGmailアドレス>
EMAIL_PASSWORD=<取得したアプリパスワード>

5.deviseの設定ファイルを手動で作成

ここが今回詰まったポイントです。
この時点でrails g devise:installコマンドを実行してもエラーとなります。
そのためrails g devise:installコマンドが何をしているか調べて必要なファイルを手動で作成して解決しました。

rails g devise:installコマンドでは下記のファイルが作成、追記される。
・config/initializers/devise.rb
・config/locales/devise.en.yml
・config/environments/development.rb
 config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }が追記

メール認証機能の実装に必要なのはdevise.rbdevelopment.rbの追記内容のため、これらを手動で追加する。

devise.rbの作成

config/initializers配下にdevise.rbを作成し、下記内容で保存する。

config/initializers/devise.rb
Devise.setup do |config|
  config.mailer_sender = ENV['EMAIL_ADDRESS']
  config.mailer = 'Devise::Mailer'
end

development.rbへの追記

development.rbに下記の追加部分の内容を追記。

config/environments/development.rb
require 'active_support/core_ext/integer/time'

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

 #〜〜一部省略〜〜

  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = true

  config.action_mailer.perform_caching = true
  config.action_mailer.default_url_options = { host: 'localhost:3001' } # 追加
  config.action_mailer.default_options = { from: ENV['EMAIL_ADDRESS'] } # 追加

 #〜〜一部省略〜〜
end

mail.rbを作成。

config/initializers配下にメール設定用のmail.rbファイルを作成し、下記内容で保存する。

config/initializers/mail.rb
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
  address: 'smtp.gmail.com',
  domain: 'gmail.com',
  port: 587,
  user_name: ENV['EMAIL_ADDRESS'],
  password: ENV['EMAIL_PASSWORD'],
  authentication: 'plain',
  enable_starttls_auto: true,
  }

DB再構築

confirmableのカラムを追加したので、DBを再作成する。

$ rake db:migrate:reset

6.動作確認

これでメール認証機能が実装できたので動作確認をしていきます。

サーバーを起動。
今回ポートは3001で起動します。

$ rails s -p 3001

Talend API Tester - Free Edition を使用してAPIの動作確認。
下記リンクからChrome拡張機能に追加できます。

ユーザ新規登録のリクエスト

ユーザ新規登録のURLはPOSTauthなのでTalend API Testerに入力をしてリクエストします。

リクエスト内容
・リクエストのMETHODをPOSTに変更する
・URLはhttp://localhost:3001/auth
nameemailpasswordconfirm_success_urlそれぞれの値を入力(emailはご自身の使用できるメールアドレス)
・ Sendボタンを押下

確認内容
・レスポンスが「200 OK」であることを確認
emailに指定したメールアドレスにタイトルが「Confirmation instructions」のメールが届く
・メールに記載の「Confirm my account」のリンクをクリックしconfirm_success_urlに指定したURLが表示される

上記が確認できれば動作確認完了です。

↓リクエスト例
スクリーンショット 2021-05-24 16.16.36.png

参考文献

2
3
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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?