はじめに
devise_token_auth
をインストールしている状態で、後からdevise
のメール認証機能を追加実装してみたところ、
詰まったポイントがあったので認証APIの実装方法と一緒に備忘録として残します。
※大前提として、今回詰まったことはdevise_token_auth
をインストールする前にrails g devise:install
しておけば発生しない問題でした。。。
最初から実装する場合は
rails g devise:install
→ rails g devise_token_auth:install User auth
の順でコマンドを実行すれば解決するようです。
ただ今回は学習も兼ねて手動で解決したのであえて、再現する形で解決方法を残します。
前提
devise_token_auth
で認証機能を実装後、後からdevise
のメール認証機能を追加で実装したい。
詰まったこと
devise
を用いてメール認証機能を実装しようとしたが、後からrails g devise:install
が実行できず、
メール認証に必要な設定ファイルが足りていなかった。
devise
とdevise_token_auth
の両方を用いる場合は
rails g devise:install
→ rails 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のインストール
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の設定箇所をコメントアウト。
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の設定は一旦除外しておきます。
# 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.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
の設定。
# 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
の修正
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
ルートの設定
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.rb
とdevise_token_auth_create_users.rb
ファイルを修正し、confirmableを有効にする。
# 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
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-rails
Gemをインストール。
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
ファイルを作成し、下記内容で保存する。
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.rb
とdevelopment.rb
の追記内容のため、これらを手動で追加する。
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
に下記の追加部分の内容を追記。
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
ファイルを作成し、下記内容で保存する。
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はPOST
のauth
なのでTalend API Testerに入力をしてリクエストします。
リクエスト内容
・リクエストのMETHODをPOST
に変更する
・URLはhttp://localhost:3001/auth
・name
、email
、password
、confirm_success_url
それぞれの値を入力(emailはご自身の使用できるメールアドレス)
・ Sendボタンを押下
確認内容
・レスポンスが「200 OK」であることを確認
・email
に指定したメールアドレスにタイトルが「Confirmation instructions」のメールが届く
・メールに記載の「Confirm my account」のリンクをクリックしconfirm_success_url
に指定したURLが表示される
上記が確認できれば動作確認完了です。