前提・実現したいこと
RailsをAPIモードで運用していて、ログイン認証にはdevise_token_authを使っています。
devise_token_authを使うという前提は変えずに、omniauthを使用したFacebookやGoogleとのSNS認証を実現したいと考えております。
APIモードでないRailsのアプリではdevise_token_authではなく、Deviseを使っていました。そちらでは実現できた機能だったので、APIモードのアプリに落とし込もうと思ったのですがうまくいきませんでした。
発生している問題・エラーメッセージ
期待していたルーティングが表示されません。
Deviseを使っていた非APIモードのアプリでは以下のようなルーティングを確認できていました。
user_facebook_omniauth_authorize GET|POST /users/auth/facebook(.:format) users/omniauth_callbacks#passthru user_facebook_omniauth_callback GET|POST /users/auth/facebook/callback(.:format) users/omniauth_callbacks#facebook user_google_oauth2_omniauth_authorize GET|POST /users/auth/google_oauth2(.:format) users/omniauth_callbacks#passthru user_google_oauth2_omniauth_callback GET|POST /users/auth/google_oauth2/callback(.:format) users/omniauth_callbacks#google_oauth2
一方で、APIモードのアプリ(devise_auth_token)使用時は以下のようなルーティングになっています。
api_v1_auth_failure GET /api/v1/auth/failure(.:format) api/v1/auth/omniauth_callbacks#omniauth_failure GET /api/v1/auth/:provider/callback(.:format) api/v1/auth/omniauth_callbacks#omniauth_success GET|POST /omniauth/:provider/callback(.:format) api/v1/auth/omniauth_callbacks#redirect_callbacks omniauth_failure GET|POST /omniauth/failure(.:format) api/v1/auth/omniauth_callbacks#omniauth_failure GET /api/v1/auth/:provider(.:format) redirect(301)
該当のソースコード
config/routes.rb
ruby
1Rails.application.routes.draw do 2 namespace :api, { format: 'json' } do 3 namespace :v1 do 4 mount_devise_token_auth_for 'User', at: 'auth', controllers: { 5 omniauth_callbacks: 'api/v1/auth/omniauth_callbacks', 6 registrations: 'api/v1/auth/registrations' 7 } 8 resources :users, only: [:index, :show], param: :username 9 end 10 end 11end
app/controllers/application_controller.rb
ruby
1class ApplicationController < ActionController::API 2 include DeviseTokenAuth::Concerns::SetUserByToken 3 4 before_action :configure_permitted_parameters, if: :devise_controller? 5 6 private 7 8 def configure_permitted_parameters 9 devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :nickname]) 10 end 11end
app/controllers/api/v1/auth/omniauth_callbacks_controller.rb
ruby
1class Api::V1::Auth::OmniauthCallbacksController < DeviseTokenAuth::OmniauthCallbacksController 2 3 def facebook 4 authorization 5 end 6 7 def google_oauth2 8 authorization 9 end 10 11 private 12 13 def authorization 14 @user = User.from_omniauth(request.env["omniauth.auth"]) 15 end 16end
app/models/user.rb
ruby
1class User < ActiveRecord::Base 2 devise :database_authenticatable, :registerable, 3 :recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:facebook, :google_oauth2] 4 include DeviseTokenAuth::Concerns::User 5 6 7 with_options presence: true do 8 validates :username, uniqueness: { case_sensitive: false }, length: { minimum: 3, maximum: 25 }, 9 format: { with: /\A[a-z\d]+\z/i } 10 validates :nickname 11 end 12end
Gemfile
ruby
1# ログイン認証 2gem 'devise' 3gem 'devise_token_auth' 4 5# SNS認証 6gem 'omniauth', '~>1.9.1' 7gem 'omniauth-facebook' 8gem 'omniauth-google-oauth2' 9gem 'omniauth-rails_csrf_protection'
試したこと
コントローラー内で
providerにfacebookを入れれば飛べるのかと考え、api/v1/auth/facebook にアクセスしてみました。
すると、以下のようなエラーが表示されました。
OmniAuth::NoSessionError (You must provide a session to use OmniAuth.):
調べてみると、APIモードでは application.rb に特殊な記述が必要ということで、以下の記述をしました。
ruby
1 config.session_store :cookie_store, key: '_interslice_session' 2 config.middleware.use ActionDispatch::Cookies # Required for all session management 3 config.middleware.use ActionDispatch::Session::CookieStore, config.session_options
すると上記のエラーは解消したのですが、続いて以下のようなエラーが発生してしまいました。
ActionController::RoutingError (No route matches [GET] "/omniauth/facebook"):
/omniauth/facebookが見つからないと言われているので、無理やりルーティングとコントローラーを用意してみました。
app/controllers/omniauth_controller.rb
ruby
1class OmniauthController < DeviseTokenAuth::OmniauthCallbacksController 2 def facebook 3 authorization 4 end 5 6 def google_oauth2 7 authorization 8 end 9 10 private 11 12 def authorization 13 @user = User.from_omniauth(request.env["omniauth.auth"]) 14 end 15end
この状態でアクセスしてみると、またもエラーが発生していました。
NoMethodError (undefined method `from_omniauth' for #<Class:0x00007efc549ba760>):
from_omniauthというメソッドはドキュメントのものなので、さすがにお手上げで質問させてもらいました。
APIモードでの開発に関しては初心者でして、devise_token_authについてもあまり詳しくないので、詳細に教えていただけると助かります。
補足情報(FW/ツールのバージョンなど)
ruby:2.6.5
rails:6.0.3
あなたの回答
tips
プレビュー