4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Express CORS Cookie

Last updated at Posted at 2023-03-17

はじめに

備忘録です。
下記の構成でアプリケーションを作成する際にCORSを解放する必要がありました。
ExpressでJSON形式のAPI
フロントエンドでReact

CORSを解放するのはCookieを設定したいためであることが多いと思います。
ついでに載せておきます。

CORSとは?

CROSS-ORIGIN-RECOSE-SHARERING
オリジンが違う場合でもアクセスできるようにする処理です

SPAの場合
バックエンドはlocalhost:4000
フロントエンドはlocalhost:3000
といったかんじで同一オリジンではないので、Cookie関連の処理ができません。
正確にいうとPOSTリクエストでCookie関連の処理ができません。 GETはできたはず?

cors

こういった設定はheaderというところに設定を記述します。
npmには便利なパッケージがあるので使います。

import cors from "cors"

app.use(
  cors({
    // cookieの送受信を可能にする
    credentials: true,
    // 許可するドメイン登録
    origin: 'url',
  }),
);

// 複数ある場合の解放方法
origin: ['url1', 'url2'],

上記は下記のようなことを行っています。

// packageを使わずに手動で設定する場合
app.use(function (req, res, next) {
  // アクセスを許可するオリジン(ドメイン)を登録
  res.header("Access-Control-Allow-Origin", "url");
  // 許可したドメインでCookie関連の処理を許可するか設定
  // Access-Control-Allow-Originを*で全て許可していた場合tureにできない
  res.header("Access-Control-Allow-Credentials", true);
  // expressの機能で、次の処理に進ませる
  next();
});

Access-Control-Allow-Originを*で全て許可していた場合tureにできないの部分ですが、
*を利用して全ての接続を許可することができるのですが、良くないみたいです。 ネットサーフィンしている時にどこかで読みました。

ここまでがフロントエンドとのCookieの送受信を可能にするためのCORSの設定です。


cookieの保存

express標準の機能でCookieの保存ができます

// 下記の構成になっています。
// 下記の記述があると、HTTPレスポンスヘッダに対して、Set-Cookieというものを付与します。
// クライアントはその値を見て、Cookieを自動で保存します。
// つまり、リクエストを飛ばせば、特に何をするまでもなく自動で保存されます。
res.cookie("key", "value", {option})
// 下記のエンドポイントを叩くと、`name: hogehoge`がCookieに保存されます。
app.get('/', (req, res) => {
  res.cookie('name', 'hogehoge', { 
    sameSite: 'none',
    secure: true,
    maxAge: 24 * 60 * 60 * 1000,
    httpOnly: true,
  });
  res.send('Cookie has been set');
});

オプションの解説をします

// 他のドメイン(別オリジン)からのPOSTでもCookieの送受信を許可
sameSite: 'none'

// HTTPSで暗号化された通信以外は拒絶する (HTTP接続を禁止)
// localhostの場合HTTPでも接続できる
// ブラウザによってsameSite noneでsecureがfalseの場合Cookieの処理を受け付けなくなっている
// Chromeのような主要ブラウザではそうなっているのでほぼ必須と言える
// つまり、sampeSiteを'none'にする場合必ずtrueである必要がある
secure: true,

// Cookieの有効期限
// ms秒で設定します。 下記は24Hです。
maxAge: 24 * 60 * 60 * 1000,

// JavaScriptでアクセスできなくする
// HTTPでしか接続できなくするものではないです (HTTPS接続を禁止するものではないです)
// この設定により不正なサイトにユーザーが誘導され、Cookieの値が抜き取られることを防ぎます
httpOnly: true, 

いろいろ説明してきましたが、クロスオリジンでCookieをやりとりするための必須項目は下記3つです。

  • CORSの設定
  • sameSite: true (Cookie保存時)
  • secure: true (Cookie保存時)

他は最悪なくても動きますが、セキュリティ的に本番環境では設定した方が良いです


cookieParser

リクエストからcookieを取得するためのpackage
ExpressはCokkieの保存には追加packageが不要ですが、Cookieの取得には追加のpackageが必要です。
自力でできないこともないですが、かなり面倒です

import cookieParser from "cookie-parser"

app.use(cookieParser());

app.get('/', (req, res) => {
  // 下記のようのreqestからcookieの値を取得できる
  const cookieValue = req.cookies.name;
  res.json({ name: cookieValue })
});

フロントエンド側の話も

axiosを使う場合を例に挙げてみます
ちなみにfetchも同じで、デフォルトではCookieの送信や受信時のCookie追加の処理をしません
fetchの場合は設定値の仕方が若干変わるので調べてみてください

// デフォルトではCookieの送信や受信後の処理を行わない
// withCredentialsをtureに設定する
const getCookie = async () => {
  const response = await axios.get(URL, {
    withCredentials: true,
  });
  console.log(response.data);
};

終わりに

Expressは情報が比較的多いのですが、SPA特有の設定調べるのに時間がかかりますね・・・

Cookieは検証ツールのApplicationタブから見ることができます。
フロントエンドからAPIを叩いた際、検証ツールのNetworkタブでheader情報を確認することができます。
Cookieの追加の場合Responseの部分にSet-Cookieがあるはずです。
自分でいろいろ検証したい場合は参考にしてください

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?