Host-Routing: Bot-Produktseite und Community-Hub getrennt
Eine Anwendung, zwei Gesichter — der Server erkennt an der Domain, welche Seite gefragt ist, und schreibt das als data-site an den <body>. Das Frontend rendert daraufhin entweder den Community-Hub wie bisher oder die neue Produktseite. - Bot-Produktseite (BotApp): Landing mit Feature-Übersicht, Befehls- referenz, Dashboard unter /dashboard, Orange als Leitfarbe - Weiterleitungen: Community-Routen auf der Bot-Domain und umgekehrt werden dauerhaft (301) auf die richtige Adresse geschickt — geteilte Devlog-Permalinks laufen also nicht ins Leere. Rechtstexte bleiben auf beiden erreichbar. - Open-Graph-Tags je Domain, inklusive eigener Vorschau für frei angelegte Seiten (Entwürfe bekommen bewusst keine) - Login: neue Einstellung für die Cookie-Domain, damit die Anmeldung auf beiden Seiten gilt; nach dem Discord-Login landet man wieder auf der Seite, von der man gestartet ist (vorher immer auf der Hauptadresse) - Alles greift erst, wenn beide Adressen im Setup eingetragen sind — bis dahin verhält sich die Anwendung unverändert Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+33
-3
@@ -1,11 +1,12 @@
|
||||
// Discord-OAuth2-Login: /auth/login → Discord → /auth/callback → signiertes Session-Cookie
|
||||
import crypto from 'node:crypto';
|
||||
import { config } from '../config.js';
|
||||
import { publicUrl, discordGuildId, memberGateEnabled } from '../runtime-settings.js';
|
||||
import { publicUrl, discordGuildId, memberGateEnabled, cookieDomain, hubUrl, botUrl } from '../runtime-settings.js';
|
||||
|
||||
const DISCORD_API = 'https://discord.com/api/v10';
|
||||
const SESSION_COOKIE = 'd4rkbot_session';
|
||||
const STATE_COOKIE = 'd4rkbot_oauth_state';
|
||||
const ORIGIN_COOKIE = 'd4rkbot_origin';
|
||||
|
||||
// Dynamisch, damit die Setup-Seite die URL ändern kann (Redirect auch im Dev-Portal eintragen!)
|
||||
const redirectUri = () => `${publicUrl()}/auth/callback`;
|
||||
@@ -50,10 +51,20 @@ export function registerAuthRoutes(app, client) {
|
||||
scope: 'identify',
|
||||
state,
|
||||
});
|
||||
// Bei getrennten Domains merken, von welcher Seite der Login kam —
|
||||
// Discord schickt immer zur selben Rücksprung-Adresse zurück.
|
||||
const host = String(request.headers.host ?? '').toLowerCase().split(':')[0];
|
||||
const origin = [hubUrl(), botUrl()].find((u) => {
|
||||
try { return new URL(u).hostname === host; } catch { return false; }
|
||||
});
|
||||
|
||||
return reply
|
||||
.setCookie(STATE_COOKIE, state, {
|
||||
path: '/auth', httpOnly: true, sameSite: 'lax', maxAge: 600, signed: true,
|
||||
})
|
||||
.setCookie(ORIGIN_COOKIE, origin ?? '', {
|
||||
path: '/', httpOnly: true, sameSite: 'lax', maxAge: 600, signed: true,
|
||||
})
|
||||
.redirect(`https://discord.com/oauth2/authorize?${params}`);
|
||||
});
|
||||
|
||||
@@ -109,15 +120,34 @@ export function registerAuthRoutes(app, client) {
|
||||
const { takeReturnTo } = await import('./sso.js');
|
||||
const returnTo = takeReturnTo(request, reply);
|
||||
|
||||
// Sonst zurück zu der Seite, von der der Login gestartet wurde
|
||||
let origin = null;
|
||||
const rawOrigin = request.cookies[ORIGIN_COOKIE];
|
||||
if (rawOrigin) {
|
||||
const unsigned = request.unsignCookie(rawOrigin);
|
||||
// Nur die beiden bekannten Adressen zulassen
|
||||
if (unsigned.valid && [hubUrl(), botUrl()].includes(unsigned.value)) {
|
||||
origin = unsigned.value;
|
||||
}
|
||||
}
|
||||
|
||||
// Mit gesetzter Cookie-Domain (z. B. .d4rkst3r.de) gilt die Anmeldung
|
||||
// auf Hub und Bot-Seite gleichzeitig
|
||||
const domain = cookieDomain();
|
||||
return reply
|
||||
.clearCookie(STATE_COOKIE, { path: '/auth' })
|
||||
.clearCookie(ORIGIN_COOKIE, { path: '/' })
|
||||
.setCookie(SESSION_COOKIE, JSON.stringify(session), {
|
||||
path: '/', httpOnly: true, sameSite: 'lax', maxAge: 7 * 24 * 3600, signed: true,
|
||||
...(domain ? { domain } : {}),
|
||||
})
|
||||
.redirect(returnTo ?? '/');
|
||||
.redirect(returnTo ?? (origin ? `${origin}/` : '/'));
|
||||
});
|
||||
|
||||
app.get('/auth/logout', async (request, reply) => {
|
||||
return reply.clearCookie(SESSION_COOKIE, { path: '/' }).redirect('/');
|
||||
const domain = cookieDomain();
|
||||
return reply
|
||||
.clearCookie(SESSION_COOKIE, { path: '/', ...(domain ? { domain } : {}) })
|
||||
.redirect('/');
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user