rails devise_token_auth ActionDispatch::Cookies::CookieOverflow について
解決したいこと
ActionDispatch::Cookies::CookieOverflow を解決したい。
サインインのたびにtokenがdbに追加されてしまうことを解決したい。
現在Rails6.1、React17.0.2でログイン機能を学習中です。
devise,devise_token_authを使用してトークンベースでの認証を目指しています。
こちらの記事(https://zenn.dev/shogo_matsumoto/articles/c6485b39c5f621#4.-%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E6%A9%9F%E8%83%BD%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E5%A4%89%E6%9B%B4)
を参考に、サインアップ、メール認証を行うことはできたのですが、何度かサインインを行うと、
ActionDispatch::Cookies::CookieOverflow (ActionDispatch::Cookies::CookieOverflow):
のエラーが表示され、バックエンドとの以降の通信がエラーとなるようになってしまいました。
エラーについて調べ、Cookie容量がオーバーしていることが原因だとわかりました。
googleデベロッパーツールにて、Cookieを確認すると、
このように表示されておりましたが、データーベースを確認したところ、
tokensカラムのデータがサインインするたびに追加されていることがわかりました。
これがエラーの原因ではないかと予測しているのですが、解決には至らずにいます。
今回記載したコードは 以下の通りです。
フロント側
import { createContext, useEffect, useState } from "react";
import { BrowserRouter, Switch, Route, Redirect } from "react-router-dom";
import { getCurrentUser } from "./api/auth";
import { Home } from "./components/Home";
import { SignIn } from "./components/SignIn";
import { SignUp } from "./components/SignUp";
export const AuthContext = createContext();
function App() {
const [loading, setLoading] = useState(true);
const [isSignedIn, setIsSignedIn] = useState(false);
const [currentUser, setCurrentUser] = useState();
// Cookieからログイン中ユーザーを取得、結果をハンドリング、最後にloadingをfalseに
const handleGetCurrentUser = async () => {
try {
const res = await getCurrentUser();
if (res?.data.isLogin === true) {
setIsSignedIn(true);
setCurrentUser(res?.data.currentUser);
} else {
console.log("no current user");
}
} catch (e) {
console.log(e);
}
setLoading(false);
};
//初回レンダリング、currentUserstateの変更時にユーザーを取得しにいく。
useEffect(() => {
handleGetCurrentUser();
}, [currentUser]);
const Private = ({ children }) => {
if (!loading) {
if (isSignedIn) {
return children;
} else {
return <Redirect to="/signin" />;
}
} else {
return <></>;
}
};
return (
<AuthContext.Provider
value={{
loading,
setLoading,
isSignedIn,
setIsSignedIn,
currentUser,
setCurrentUser,
}}
>
<BrowserRouter>
<Switch>
<Route exact path="/signup">
<SignUp />
</Route>
<Route exact path="/signin">
<SignIn />
</Route>
<Private>
<Route exact path="/">
<Home />
</Route>
</Private>
</Switch>
</BrowserRouter>
</AuthContext.Provider>
);
}
export default App;
import { client } from "./client";
import Cookies from "js-cookie";
// サインアップ
export const signUp = (params) => {
return client.post("/auth", params);
};
// サインイン
export const signIn = (params) => {
return client.post("/auth/sign_in", params);
};
// サインアウト
export const signOut = () => {
return client.delete("/auth/sign_out", {
headers: {
"access-token": Cookies.get("_access_token"),
client: Cookies.get("_client"),
uid: Cookies.get("_uid"),
},
});
};
export const getCurrentUser = () => {
if (
!Cookies.get("_access_token") ||
!Cookies.get("_client") ||
!Cookies.get("_uid")
)
return
return (
client.get("/auth/sessions", {
headers: {
"access-token": Cookies.get("_access_token"),
"client": Cookies.get("_client"),
"uid": Cookies.get("_uid"),
},
})
)
};
バックエンド側
該当するソースコード
class Api::V1::Auth::SessionsController < ApplicationController
def index
if current_api_v1_user
render json: {is_login: true, current_user: current_api_v1_user }
else
render json: {is_login: false, message: "ユーザーが存在しません"}
end
end
end
例)
DeviseTokenAuth.setup do |config|
config.change_headers_on_each_request = false
config.token_lifespan = 2.weeks
config.token_cost = Rails.env.test? ? 4 : 10
config.max_number_of_devices = 2
config.headers_names = {:'access-token' => 'access-token',
:'client' => 'client',
:'expiry' => 'expiry',
:'uid' => 'uid',
:'token-type' => 'token-type',
:'authorization' => 'authorization' }
end
require_relative "boot"
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_mailbox/engine"
require "action_text/engine"
require "action_view/railtie"
require "action_cable/engine"
# require "sprockets/railtie"
require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module Myapp
class Application < Rails::Application
config.load_defaults 6.1
config.i18n.default_locale = :ja
config.api_only = true
config.session_store :cookie_store, key: '_interslice_session'
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore, config.session_options
config.middleware.use ActionDispatch::Flash
config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'localhost:8000'
resource '*',
:headers => :any,
:expose => ['access-token', 'expiry', 'token-type', 'uid', 'client'],
:methods => [:get, :post, :options, :delete, :put]
end
end
end
end
大変お見苦しいコードかとは思いますが、ご教授いただけたら幸いです。
記載が足りないファイル等ありましたらご指摘いただけるとありがたいです。