From 1f5e43855eb3b4c0b444c7091b2ed4861fc0f2c1 Mon Sep 17 00:00:00 2001 From: Ryan Barlow <7389646+ryanbarlow97@users.noreply.github.com> Date: Sat, 10 Oct 2026 20:18:53 +0000 Subject: [PATCH 1/3] Document Discord sign-in on ProvinceSystem branch previews Co-Authored-By: Claude Opus 5.5 --- projects/ProvinceSystem/DEPLOY.md | 7 ++++-- .../docs/identity/auth-security.md | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/projects/ProvinceSystem/DEPLOY.md b/projects/ProvinceSystem/DEPLOY.md index 3cb296d..68b4c17 100644 --- a/projects/ProvinceSystem/DEPLOY.md +++ b/projects/ProvinceSystem/DEPLOY.md @@ -29,8 +29,11 @@ the `ps-preview-router` Caddy container (`127.0.0.1:8090`, behind the `*.tfminec `dependabot/**` branches are skipped. - **Data:** the first `up` copies the dev backend's data, input, defines and output folders, with sign-in sessions, OAuth states and link codes deleted. A redeploy of the same branch keeps its data. -- **Environment:** only `SKINS_DEV=1`, `SITE_PUBLIC_URL` and random `STAFF_KEY`/`PLUGIN_KEY`. Discord sign-in, Patreon, - CoreProtect and patch notes are off, so signed-in and staff pages cannot be tried on a preview. +- **Environment:** only `SKINS_DEV=1`, `SITE_PUBLIC_URL` and random `STAFF_KEY`/`PLUGIN_KEY`, plus + `SIGN_IN_SITE=https://dev.tfminecraft.net` built into the backend image. Patreon, CoreProtect and patch notes are off. +- **Sign-in:** Discord sign-in goes through dev, which needs `PREVIEW_SIGN_IN_DOMAIN=tfminecraft.net`, and keeps the + dev account's role ([Branch previews](docs/identity/auth-security.md#branch-previews)). A player signed in on dev + is signed in on a preview without seeing Discord. - **Access:** public, with `X-Robots-Tag: noindex, nofollow`. - **Limits:** at most four previews at once (`up` exits 3); backend 2 GB / 1.5 CPU, frontend 1 GB / 1 CPU. - **Lifetime:** each `up` sets the expiry to 90 minutes later; `ps-preview-reap.timer` runs `reap` every minute. diff --git a/projects/ProvinceSystem/docs/identity/auth-security.md b/projects/ProvinceSystem/docs/identity/auth-security.md index f64f343..c2487a0 100644 --- a/projects/ProvinceSystem/docs/identity/auth-security.md +++ b/projects/ProvinceSystem/docs/identity/auth-security.md @@ -46,6 +46,31 @@ Some answers pause every check: asked, and "I've joined, check again" falls back to a Discord sign-in. Source: [`guild_check.py`](https://github.com/TF-Minecraft/ProvinceSystem/blob/main/backend/src/auth/guild_check.py). +### Branch previews + +Discord returns players only to registered callbacks, so a preview at +`https://.tfminecraft.net` signs in through dev instead +([`preview_sign_in.py`](https://github.com/TF-Minecraft/ProvinceSystem/blob/main/backend/src/auth/preview_sign_in.py)). +Preview images set `SIGN_IN_SITE=https://dev.tfminecraft.net` and hold no Discord settings. +Dev sets `PREVIEW_SIGN_IN_DOMAIN=tfminecraft.net`. + +1. The preview's `/auth/discord/start` stores a random state in its state cookie and + sends the browser to dev's `/api/auth/preview/start` with the state, the preview's + origin and the return path. +2. Dev accepts only `https://.` origins whose slug is not + reserved. Without a dev session, it signs the player in with Discord and Discord's + callback returns them to that route. +3. Dev refreshes the session's guild check with the bot, stores a hashed single-use + ticket for that preview (120 seconds), and redirects to the preview's + `/api/auth/preview/callback`. +4. The preview checks the state against its cookie, then posts the ticket and its + origin to dev's `/api/auth/preview/redeem`. Dev deletes the ticket and returns the + Discord identity, website role and guild check. +5. The preview opens its own session with that role and check. + +A player already signed in on dev skips Discord. The preview never sees the dev session +or the Discord secret, and its changes stay in its own copy of dev's data. + ## Microsoft link Signed-in players can link Minecraft by signing in with Microsoft instead of From 08c3e533cc9cfac93948ac4c81040d6a2582543b Mon Sep 17 00:00:00 2001 From: Ryan Barlow <7389646+ryanbarlow97@users.noreply.github.com> Date: Sat, 10 Oct 2026 20:28:35 +0000 Subject: [PATCH 2/3] Note the Discord fallback and log redaction for preview sign-in Co-Authored-By: Claude Opus 5.5 --- projects/ProvinceSystem/docs/identity/auth-security.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/projects/ProvinceSystem/docs/identity/auth-security.md b/projects/ProvinceSystem/docs/identity/auth-security.md index c2487a0..37c4ec2 100644 --- a/projects/ProvinceSystem/docs/identity/auth-security.md +++ b/projects/ProvinceSystem/docs/identity/auth-security.md @@ -60,9 +60,10 @@ Dev sets `PREVIEW_SIGN_IN_DOMAIN=tfminecraft.net`. 2. Dev accepts only `https://.` origins whose slug is not reserved. Without a dev session, it signs the player in with Discord and Discord's callback returns them to that route. -3. Dev refreshes the session's guild check with the bot, stores a hashed single-use - ticket for that preview (120 seconds), and redirects to the preview's - `/api/auth/preview/callback`. +3. Dev refreshes the session's guild check with the bot. If the bot cannot answer and + the check is over 15 minutes old, dev signs the player in with Discord again. It then + stores a hashed single-use ticket for that preview (120 seconds) and redirects to the + preview's `/api/auth/preview/callback`. Access logs drop the query on both routes. 4. The preview checks the state against its cookie, then posts the ticket and its origin to dev's `/api/auth/preview/redeem`. Dev deletes the ticket and returns the Discord identity, website role and guild check. From 1a8c8d827eb568a702b044b3ffd597ccdf754bdf Mon Sep 17 00:00:00 2001 From: Ryan Barlow <7389646+ryanbarlow97@users.noreply.github.com> Date: Sat, 10 Oct 2026 20:33:18 +0000 Subject: [PATCH 3/3] Qualify when preview sign-in skips Discord Co-Authored-By: Claude Opus 5.5 --- projects/ProvinceSystem/DEPLOY.md | 2 +- projects/ProvinceSystem/docs/identity/auth-security.md | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/projects/ProvinceSystem/DEPLOY.md b/projects/ProvinceSystem/DEPLOY.md index 68b4c17..d30bbc8 100644 --- a/projects/ProvinceSystem/DEPLOY.md +++ b/projects/ProvinceSystem/DEPLOY.md @@ -33,7 +33,7 @@ the `ps-preview-router` Caddy container (`127.0.0.1:8090`, behind the `*.tfminec `SIGN_IN_SITE=https://dev.tfminecraft.net` built into the backend image. Patreon, CoreProtect and patch notes are off. - **Sign-in:** Discord sign-in goes through dev, which needs `PREVIEW_SIGN_IN_DOMAIN=tfminecraft.net`, and keeps the dev account's role ([Branch previews](docs/identity/auth-security.md#branch-previews)). A player signed in on dev - is signed in on a preview without seeing Discord. + usually skips Discord. - **Access:** public, with `X-Robots-Tag: noindex, nofollow`. - **Limits:** at most four previews at once (`up` exits 3); backend 2 GB / 1.5 CPU, frontend 1 GB / 1 CPU. - **Lifetime:** each `up` sets the expiry to 90 minutes later; `ps-preview-reap.timer` runs `reap` every minute. diff --git a/projects/ProvinceSystem/docs/identity/auth-security.md b/projects/ProvinceSystem/docs/identity/auth-security.md index 37c4ec2..ae264f0 100644 --- a/projects/ProvinceSystem/docs/identity/auth-security.md +++ b/projects/ProvinceSystem/docs/identity/auth-security.md @@ -61,7 +61,9 @@ Dev sets `PREVIEW_SIGN_IN_DOMAIN=tfminecraft.net`. reserved. Without a dev session, it signs the player in with Discord and Discord's callback returns them to that route. 3. Dev refreshes the session's guild check with the bot. If the bot cannot answer and - the check is over 15 minutes old, dev signs the player in with Discord again. It then + the check is over 15 minutes old, or the preview asked for a recheck because the + player was already signed in there ("I've joined, check again"), dev signs the + player in with Discord again. It then stores a hashed single-use ticket for that preview (120 seconds) and redirects to the preview's `/api/auth/preview/callback`. Access logs drop the query on both routes. 4. The preview checks the state against its cookie, then posts the ticket and its @@ -69,7 +71,8 @@ Dev sets `PREVIEW_SIGN_IN_DOMAIN=tfminecraft.net`. Discord identity, website role and guild check. 5. The preview opens its own session with that role and check. -A player already signed in on dev skips Discord. The preview never sees the dev session +A player already signed in on dev skips Discord unless the bot cannot answer one of +those checks. The preview never sees the dev session or the Discord secret, and its changes stay in its own copy of dev's data. ## Microsoft link