RailsAPIモードとNuxtの組みわせでハマったこと

投稿者
だいそん

フロントとバックエンドで分けて開発する際にクッキー・セッションベースの認証でいつも詰まるのでここに記しておきます。

前提

サーバサイドはRails APIモード。バージョンは下記の通りです。

$ bundle exec rails -v
Rails 6.0.2.1

$ ruby -v
ruby 2.6.4p104 (2019-08-28 revision 67798) [x86_64-darwin18]

フロントはNuxt.js。バージョンは下記の通りです。

$ npx nuxt --version
@nuxt/cli v2.11.0

$ node -v
v12.13.1

TL;DR

下記を対応すればOKです。

Rails側

  • CORSの設定をする
  • api_onlyfalseにする

Nuxt側

  • Proxyの設定をする

具体的手順

1. CORSの設定をする

Railsはlocalhost:3001で起動、Nuxtはlocalhost:3000で起動するのでそのままAPI通信しようとするとCORS制約にかかる。

Access to XMLHttpRequest at 'http://localhost:3001/session' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

オリジン間リソース共有 (CORS)

そのため、まずRails側でCORSの設定をする必要がある。

rack-corsをインストールする

# Gemfile
gem 'rack-cors'

application.rbを修正する

    # config/application.rb
    
    config.middleware.insert_before 0, Rack::Cors do
      allow do
        # 許可するドメイン
        origins "localhost:3000"
        # 許可するヘッダとメソッドの種類
        resource "*",
                 headers: :any,
                 methods: [:get, :post, :patch, :delete, :head, :options]
      end
    end

2. Proxyの設定をする

APIを投げる時おそらくこのように投げるはず。

this.$axios.post("/api/v1/session", { session: this.loginForm });

ただ先述の通りフロントとサーバでドメインが違うのでこのままだと

http://localhost:3000/api/v1/session

にリクエスト投げることになってしまう。 それを解消するにはProxyの設定をする必要がある。

@nuxtjs/proxyをインストールする

$ yarn add @nuxtjs/proxy

nuxt.config.jsを修正する

  modules: [
    '@nuxtjs/axios',
    '@nuxtjs/proxy' // 追記
  ],

  // 追記
  proxy: {
    '/api': {
      target: 'http://localhost:3001',
      pathRewrite: {
        '^/api': '/api'
      }
    },
  },

ここまでの設定でCORSの問題はクリアできるので正常にPOSTができるはず。 ただ、セッションがうまく引き継がれないのでログイン状態が保持できない。(ログイン処理自体はうまくいっているにも関わらずセッションに値が保持されない。)

下記gifのサンプルアプリではログインボタンを押すとログイン処理が行われ、成功するとマイページに飛ぶ実装にしています。マイページではログイン中のユーザーを取得して画面に表示する処理を書いています。 ログイン自体はうまくいってるんのですが、マイページにてログイン中のユーザーが取ってこれてません。 セッション保持されている

サーバ側でcurrent_userやsessionを覗いてみてもnil。

それを解消するには次のことをやる必要があるらしいです。

3. api_onlyfalseにする

# config/application.rb
    
config.api_only = false

これで無事ログインできました。

セッション保持されている

サンプルリポジトリのリンクも貼っておきます。

バックエンド https://github.com/DaichiSaito/nuxt_example_api

フロントエンド https://github.com/DaichiSaito/nuxt_example_front

誰かのお役に立てれば幸いです。

一緒にスタートアップを盛り上げませんか?
技術ブログ始めました!
2019/12/24
フラッシュメッセージを含めたアカウントロック実装方法(gem Sorceryを使用)
2020/01/28