SPA(React)でログインを実装する時にフロント側のCookieにtokenを保存してはいけない

Share this post

SPA(React)のログイン処理の脆弱性について

railsでログイン処理を作ったときに勉強になったことがあったので書き記したいと思います。

devisedevise_token_authを使った時のことです。
ログイン時にリクエストが成功した際は access-token,client,uidの3つのheader情報をreact側に返すようにしていました。

そして、その情報をreact側でcookieに保存していました。(webstorageよりcookieの方が安全と聞いていたため)
その時は、react側であらゆるAPIに対してのリクエストをこんな感じで書いていました。

export const client = axios.create({
    baseURL: 〇〇
});
import Cookies from "js-cookie"

client.get("/auth/sessions", { headers: {
    "access-token": Cookies.get("_access_token"),
    "client": Cookies.get("_client"),
    "uid": Cookies.get("_uid")
  }})

しかし、この方法ではセキュリティ的に安全とは言えませんでした。
なぜなら、cookieではhttponly属性と言うものがありこれを使うことによりjavascriptを使った攻撃を弾くことができます。(cookieを取得できないようにできる)

ですが、javascriptでcookieファイルを作り出して、httponly属性を付与すると取得ができないファイルと化してしまうため、必然的にhttponly属性の付与が不可能でした。
(根本的にhttponly属性はサーバー側に付与してもらうのが普通のようです。)
https://stackoverflow.com/questions/14691654/set-a-cookie-to-httponly-via-javascript

つまり、フロント側で生成したcookieはhttponlyを付けていないcookieとなるため、webstorageと全く一緒でセキュリティ的リスクがあります。
あとは単純にユーザがブラウザの開発者コンソールから見た時に「このアプリのtoken、httponly付けてないじゃん、、」と思われ、不安を煽ってしまうのもデメリットだと思います。

そのため、apiからhttpolnyを付与したcookieファイルをgetしてcredetialsオプションを付けてあげる必要があります。

export const client = axios.create({
    withCredentials: true,
    baseURL: 〇〇
});

そしてrails側(API側)でもcredentialsをオンにすることでクロスドメインでcookieのやりとりをできるようにします。
そうすることによってAPIからhttponly属性を付与したcookieをreactに共有することができました。
ログイン処理のセキュリティリスクは出来るだけ排除したいので気をつけながら開発しましょう!

Share this post