35
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

DeviseとDevise token authを共存させる(後から追加する)

追記(2019年11月7日)

条件はわかりませんが、おそらくバージョンによってInvalidAuthenticityTokenエラーがでる場合があります。

ActionController::InvalidAuthenticityToken in DeviseTokenAuth::RegistrationsController#create

その場合はprotect_from_forgeryをフォーマットによって変更することで対応しています。
これが正しい方法かなのかはわかりません。誰か教えてください。

controllers/application_controller
class ApplicationController < ActionController::Base
  protect_from_forgery unless: -> { request.format.json? } 
  ...
end

Devise Token Authについて

Deviseのユーザー登録機能を利用して、トークンの発行、トークンによる認証を可能にするgemです。
注意点として、

・普通に入れるとAPI専用として作ることになる(/users/sign_inとか使えない)
・(Deviseのみで開発していたアプリへの)後からDevise Token Authを追加することを前提に作られていない

ということで、この二点を解決する方法を調べました。

セットアップ

Gemfileに追加します。あとから追加する場合もこの状態にします。

Gemfile
...
gem 'devise'
gem 'devise_token_auth'
gem 'omniauth'
... 
bundle install #または bundle install --path vendor/bundle

Deviseのインストール(運用中の場合はスキップ)

すでにDeviseが入っている場合は不要です。

rails generate devise:install
rails db:migrate

Deviseの詳細なセットアップについては、以下の記事が参考になります。https://qiita.com/cigalecigales/items/f4274088f20832252374

Devise token authのインストール

次に、Devise token authをインストールします。

rails generate devise_token_auth:install User auth

Routeを修正

config/routes.rb
Rails.application.routes.draw do
  # 先にDevise用のルート
  devise_for :users

  # /api/v1/authでアクセス可能
  namespace :api do
    scope :v1 do
      mount_devise_token_auth_for 'User', at: 'auth'
    end
  end
end

application_controller.rbを修正

通常のapplicatino_controller.rbに加えて、API用のapplication_controller.rbを作成します。

まずは通常のapplication_controllerを修正

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  #include DeviseTokenAuth::Concerns::SetUserByToken # この行を削除
  protect_from_forgery with: :exception
  before_filter :set_host # この行を追加

  def set_host
    Rails.application.routes.default_url_options[:host] = request.host_with_port
  end
end

Devise Token Auth用のapplication_controller.rbをapi/v1以下に作成

app/controllers/api/v1/application_controller.rb
module Api
  module V1
    class ApplicationController < ActionController::API # Note: here is not ::BASE
      include DeviseTokenAuth::Concerns::SetUserByToken
      protect_from_forgery with: :null_session
    end
  end
end

マイグレーションファイルを修正

Devise Token Auth用に生成されたマイグレーションファイルと、通常のDevise導入時に生成されたマイグレーションファイルを比較しながら、被っているものを削除してマイグレーションファイルを調整します。

モデルを修正

user.rb
class User < ApplicationRecord
  include DeviseTokenAuth::Concerns::User #ここだけがDevise Token Auth用

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end

Initializerを修正

トークンの有効期限などを設定します。

config/initializers/devise_token_auth.rb
DeviseTokenAuth.setup do |config|
  config.enable_standard_devise_support = true
  config.default_confirm_success_url = "confirmed"# この行を追加

  config.change_headers_on_each_request = false
  config.token_lifespan = 1.month

  config.headers_names = {:'access-token' => 'access-token',
                          :'client' => 'client',
                          :'expiry' => 'expiry',
                          :'uid' => 'uid',
                          :'token-type' => 'token-type' }
end

作りながら書いたので、不完全な内容になっているかもしれません。何か問題があれば随時修正します。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
35
Help us understand the problem. What are the problem?