ものづくりのブログ

うちのネコを題材にしたものづくりができたらいいなと思っていろいろ奮闘してます。

【docker】ドメインの異なるサービス間で cookie を共有できるか検証

docker を使ってドメインの異なるサービス間で cookie を共有できるか検証してみました。

環境

構成

sample_apps/
├── app1/
│   ├── app.py
│   ├── static/
│   └── templates/
├── app2/
│   ├── app.py
│   ├── static/
│   └── templates/
├── certs/
├── Dockerfile
├── requirements.txt
└── docker-compose.yml

mkcert を使用してローカル開発用の証明書を作成

mkcert を使用してローカル開発用の証明書を作成します。

# certs ディレクトリに移動
cd sample_apps/certs

# mkcertを使って証明書作成
mkcert -install
mkcert localhost

Dockerfile

FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY certs /certs
COPY app /app

EXPOSE 443 8443
CMD ["python", "app.py"]

docker-compose.yml

version: "3.9"
services:
  app1:
    build: .
    container_name: app1
    ports:
      - "8443:8443"
    volumes:
      - ./certs:/certs
      - ./app1:/app
  app2:
    build: .
    container_name: app2
    ports:
      - "443:443"
    volumes:
      - ./certs:/certs
      - ./app2:/app

app

app1
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def home():
    return render_template('index.html')

@app.route("/view_cookies")
def view_cookies():
    return render_template('view_cookies.html')

@app.route("/delete_cookies")
def delete_cookies():
    return render_template('delete_cookies.html')

@app.route("/sample_client")
def sample_client():
    return render_template('sample-client.html')

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8443, ssl_context=(
        "/certs/localhost.pem", "/certs/localhost-key.pem"
    ))
app2
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def home():
    return render_template('index.html')

@app.route("/view_cookies")
def view_cookies():
    return render_template('view_cookies.html')

@app.route("/delete_cookies")
def delete_cookies():
    return render_template('delete_cookies.html')

@app.route("/sample_container")
def sample_container():
    return render_template('sample-container.html')

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=443, ssl_context=(
        "/certs/localhost.pem", "/certs/localhost-key.pem"
    ))

html

cookie を作成・削除するページは省略します。

app1/templates/sample-client.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>sample-client</title>
</head>
<body>
    <script>
        window.addEventListener("message", (event) => {
            if (event.origin !== "https://example.com") return;
            console.log("Received data:", event.data);
        });

        function appendIframeContainer() {
            var sampleContainer = document.createElement('iframe');
            sampleContainer.src = 'https://example.com/sample_container';
            sampleContainer.style.cssText = 'width: 0px; height: 0px; display: none;';
            document.body.appendChild(sampleContainer);
        }
    
        if (document.readyState == 'loading') {
            document.addEventListener('DOMContentLoaded', appendIframeContainer());
        } else {
            appendIframeContainer();
        }
    </script>
</body>
</html>
app2/templates/sample-container.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sender</title>
</head>
<body>
    <h1>Sender Page</h1>
    <script>
        var data = {'specificCookie': document.cookie};
        console.log(data)
        window.parent.postMessage(JSON.stringify(data), '*');
    </script>
</body>
</html>

アプリ立ち上げ

docker-compose build
docker-compose up  

環境準備(/etc/hosts)

127.0.0.1 example.com
127.0.0.1 app2.local

条件

以下の条件でドメインの異なるサービス間で cookie が共有できるか検証します。

  • Secure 属性: HTTPS 通信時のみ Cookie を送信
  • SameSite 属性: クロスサイトリクエストの制御に利用
cookie 名 Secure SameSite 備考
cookie_01 sample_01
cookie_02 sample_02
cookie_03 sample_03 None


検証

内容

検証結果

  • SameSite に None を入れないと少なくとも Chrome は cookie は共有できなさそう
  • SameSite を None にするには Secure は必須


参考情報

SameSite 属性

空の場合はブラウザによって None だったり Lax だったり。。。
chrome は Lax 扱いで... Firefox と Safari はまだゆるそう。。。

None

全ての cross-site なリクエストに対して Cookie が付与される。

Strict

same-site に対するリクエストにのみ Cookie が付与される。

Lax

None と Strict の間に位置するようなものとのこと。。。
GET リクエストや method=GET のフォームによる画面遷移のようなトップレベルナビゲーションの場合のみ、サイト間通信であっても送信先サイトで設定された Cookie は送信先に渡される。
iframe 経由はダメそう。

ブラウザの互換性

developer.mozilla.org