3rd Party Cookieの挙動をローカル環境で検証する
株式会社バニッシュ・スタンダードでバックエンドエンジニアをやっている西谷です。
早いもので、いつの間にか入社して2ヶ月が経過しました。
今回はローカル環境でHTTPSで動作するサーバーを構築してサイト間通信でのCookieの送受信の挙動を検証してみたので、共有します。
やりたいこと
以下のようなサイト間での通信でCookieの送受信が行えるかを、ローカル環境上で検証するのが今回の目標です。
-
1st.example.com
:ファーストパーティサイト -
3rd.example.net
:サードパーティAPI
以降、1st.example.com
を1st、3rd.example.net
を3rdと呼ぶことにします。
課題
サクッと検証したいところですが、以下のような課題が存在します。
- サイト間通信でのCookie送受信となるため、
SameSite=None
の指定が必要 -
SameSite=None
の場合、Secure
属性の指定が必須→検証のためにローカル環境のHTTPS化が必要
ローカル環境の準備
検証に必要なコードと、HTTPSで動作するサーバーを準備します。
ローカルサーバーの準備
今回はNode.jsでローカルサーバーを立てます。
セットアップ
サーバーで使用するExpressをインストールします。
$ npm init
$ npm install express
サーバーのコードを作成
今回は楽をするため、1つのコードに1st,3rd用のコードを混在させます。
以下の3つのエンドポイントを定義してあります。
-
/
(1st用) -
/write-cookie
(3rd用) -
/read-cookie
(3rd用)
const express = require('express');
const app = express();
const port = 3000;
// CORSの設定
const setCorsHeaders = (res) => {
res.setHeader('Access-Control-Allow-Origin', 'https://1st.example.com');
res.setHeader('Access-Control-Allow-Credentials', true);
}
// -------------------- 1st.example.com用 --------------------
// ユーザーが直接訪れるサイトのHTMLを配信
app.get('/', (req, res) => {
res.sendFile(`${__dirname}/index.html`);
})
// -------------------- 3rd.example.net用 --------------------
// Cookieを作成
app.get('/write-cookie', (req, res) => {
setCorsHeaders(res);
res.cookie(
'cookie',
'value',
{
sameSite: 'none',
secure: true,
}
);
res.json({});
})
// クライアントから送信されたCookieの内容を読み取って返す
app.get('/read-cookie', (req, res) => {
setCorsHeaders(res);
res.json(req.headers.cookie);
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
})
1st用のHTML
1stにアクセスすると返ってくるHTMLです。
scriptタグ内のJSで、/write-cookie
を叩いてレスポンスを受け取った後に read-cookie
を叩くようになっています。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ファーストパーティサイト</title>
<script type="text/javascript">
const sendRequest = (path, method, onLoad = undefined) => {
const xhr = new XMLHttpRequest();
if (onLoad !== undefined) {
xhr.addEventListener("load", onLoad);
}
xhr.open(method, `https://3rd.example.net/${path}`);
xhr.withCredentials = true;
xhr.send();
}
const reqListener = () => {
sendRequest('read-cookie', 'GET');
}
sendRequest('write-cookie', 'GET', reqListener);
</script>
</head>
<body>
ファーストパーティサイト
</body>
</html>
hostsの設定
検証で使用するドメインに接続できるように、hostsを編集します。
127.0.0.1 1st.example.com
127.0.0.1 3rd.example.net
https-portalを使用するための定義
上記のローカルサーバーを、https-portalでHTTPS化します。
services:
https-portal:
image: steveltn/https-portal:1
ports:
- '80:80'
- '443:443'
environment:
DOMAINS: '1st.example.com -> http://host.docker.internal:3000, 3rd.example.net -> http://host.docker.internal:3000'
STAGE: 'local'
Cookieの挙動を検証
ローカル環境の準備ができたので、準備した環境を使って検証を進めていきます。
起動
ローカルサーバーとhttps-portalを起動します。
$ node index.js
$ docker compose up
挙動を確認
https://1st.example.com/ に接続して、サイト間通信のCookieの挙動を確認します。
Cookieの書き込みができていることを確認
Dev-ToolsのApplicationタブで、サイト間通信でのCookieの書き込みが成功していることを確認します。
(https://3rd.example.net/write-cookie でSet-Cookieが行われています)
Cookieの読み取りができていることを確認
Dev-ToolsのNetworkタブで、サイト間通信でのCookieの読み込みが成功していることを確認します。(https://3rd.example.net/read-cookie では、読み込んだCookieの内容をそのままレスポンスで返しています)
まとめ
https-portalを使うことで、ローカル環境のHTTPS化を簡単に行うことができました。
実際にサーバーを動かして検証することで、サイト間通信でのCookie送受信に必要な設定について理解を深めることができました!
Discussion