Rails APIモードでomniauth導入時に「OmniAuth::NoSessionError (You must provide a session to use OmniAuth.)」が出る場合の対処

こんにちは!kossyです!




さて、今回はRails APIモードでomniauth導入時に「OmniAuth::NoSessionError (You must provide a session to use OmniAuth.)」が出る場合の対処法をブログに残してみたいと思います。




環境

Ruby 2.6.8
Rails 6.0.4
devise_token_auth 1.1.5
omniauth 2.0.4



ActionDispatchミドルウェアを導入する

RailsAPIモードの場合、セッションやcookie等のミドルウェアがデフォルトでインストールされません。

omniauthを使う場合、セッションのミドルウェアは必須になるため、ActionDispatchミドルウェアを導入する必要があります。

application.rbを以下のように編集してください。

module SampleApi
  class Application < Rails::Application
    config.load_defaults 6.0
    config.api_only = true

    # ↓追加↓
    # For Omniauth
    config.session_store :cookie_store, key: '_interslice_session'
    config.middleware.use ActionDispatch::Cookies # Required for all session management
    config.middleware.use ActionDispatch::Session::CookieStore, config.session_options
    # ↑ここまで↑
end

omniauthのエラー定義を見てみる

OmniAuth::NoSessionErrorの処理の中身を見に行ってみます。

omniauth/strategy.rb at master · omniauth/omniauth · GitHub

    # The logic for dispatching any additional actions that need
    # to be taken. For instance, calling the request phase if
    # the request path is recognized.
    #
    # @param env [Hash] The Rack environment.
    def call!(env) # rubocop:disable CyclomaticComplexity, PerceivedComplexity
      unless env['rack.session']
        error = OmniAuth::NoSessionError.new('You must provide a session to use OmniAuth.')
        raise(error)
      end

      @env = env

      warn_if_using_get_on_request_path

      @env['omniauth.strategy'] = self if on_auth_path?

      return mock_call!(env) if OmniAuth.config.test_mode

      begin
        return options_call if on_auth_path? && options_request?
        return request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
        return callback_call if on_callback_path?
        return other_phase if respond_to?(:other_phase)
      rescue StandardError => e
        raise e if env.delete('omniauth.error.app')

        return fail!(e.message, e)
      end

      @app.call(env)
    end

重要なのはこの箇所ですね。

unless env['rack.session']
  error = OmniAuth::NoSessionError.new('You must provide a session to use OmniAuth.')
  raise(error)
end

env['rack.session'] がfalseの場合、OmniAuth::NoSessionErrorをraiseしています。

まとめ

そもそも env['rack.session'] ってなんやねんな状態なので、近々 ActionDispatch周りのミドルウェアも含めて、コードリーディング記事を書くと思います。