Skip to content

Authentication DE

Domekologe edited this page Jun 30, 2026 · 1 revision

Authentifizierung

🌐 English · Deutsch

Das Dashboard authentifiziert Nutzer per Discord OAuth2 und hält die Session in einem signierten, serverseitig verwalteten Cookie. Das Sicherheitsmodell folgt einem Leitsatz: Geheimnisse erreichen nie den Browser. Das Discord-Client-Secret und das Gateway-Token liegen nur im SvelteKit-Server (dem BFF), das Gateway akzeptiert nur localhost plus Token, und jede privilegierte Aktion wird botseitig erneut gegen Reds Berechtigungssystem geprüft. Diese Seite erklärt den Login-Flow, das Session-Modell und die Berechtigungsstufen.

Screenshot: Discord-OAuth2-Consent-Screen

Der OAuth2-Login-Flow

  1. Der Nutzer klickt Mit Discord anmelden. Der BFF (GET /auth/login) erzeugt einen zufälligen state-Wert, legt ihn in einem kurzlebigen httpOnly-Cookie ab und leitet den Browser zur Discord-Authorize-URL mit den Scopes identify und guilds weiter.
  2. Der Nutzer bestätigt bei Discord und wird zurück an DISCORD_REDIRECT_URI (/auth/callback) geschickt.
  3. Der BFF (GET /auth/callback) prüft den zurückgegebenen state gegen das Cookie und tauscht dann den Authorization-code serverseitig per DISCORD_CLIENT_SECRET gegen ein Access-Token.
  4. Mit diesem Token holt der BFF den Discord-Nutzer (identify) und leitet die UI-Locale ab (de-DE für deutsche Nutzer, sonst en-US).
  5. Der BFF erzeugt eine Session und setzt das signierte Session-Cookie. Der Browser sieht weder das Client-Secret noch die rohe Token-Verarbeitung.
Browser ──/auth/login──▶ BFF ──Redirect──▶ Discord
Browser ◀──Consent────── Discord
Browser ──/auth/callback (code,state)──▶ BFF ──code→Token (Secret)──▶ Discord
                                          BFF ◀──User──────────────── Discord
Browser ◀──Set-Cookie: dks_session────── BFF

Sessions (signierte Cookies, serverseitiger BFF)

Die Session steckt in einem Cookie namens dks_session. Es ist kein opaker Datenbank-Key, sondern die Nutzer-Payload plus eine HMAC-SHA256-Signatur mit SESSION_SECRET:

dks_session = base64url(payload) . base64url(HMAC-SHA256(payload, SESSION_SECRET))
Eigenschaft Wert
Cookie-Name dks_session
Signatur HMAC-SHA256, mit konstanter Zeit verglichen
Flags httpOnly, sameSite=lax, in Produktion secure
Lebensdauer 7 Tage
Payload User-ID, Username, Avatar, Locale, Issued-at (iat), Token-Daten

Da das Cookie signiert (nicht verschlüsselt) ist, kann es nicht manipuliert werden: Jede Änderung der Payload bricht den HMAC. Signieren und Prüfen passieren ausschließlich im BFF (lib/server/session.ts), das SESSION_SECRET verlässt den Server also nie.

Session-Invalidierung (Epoch)

Der Bot-Owner kann alle Sessions auf einmal invalidieren („Sessions zurücksetzen" in Einstellungen). Das setzt einen session_epoch-Zeitstempel im Cog. Bei jeder Anfrage vergleicht der BFF die iat der Session mit der aktuellen Epoch (für ~60 s gecacht, um einen Round-Trip pro Anfrage zu sparen) und verwirft Sessions, die älter als die Epoch sind.

Das Gateway: localhost + Token

Der BFF spricht über das JSON-RPC-Gateway des Cogs mit dem Bot. Zwei Dinge schützen es:

  • Localhost-Bindung. Das Gateway lauscht standardmäßig auf 127.0.0.1 – aus dem Netzwerk nicht erreichbar.
  • Geteiltes Token. Jede BFF-Anfrage trägt den Header X-Dashboard-Token. Der Cog vergleicht ihn in konstanter Zeit (compare_digest). Nur der BFF kennt das Token.

Der Browser spricht nie direkt mit dem Gateway. Er ruft immer nur die eigenen /api/*-Endpunkte des BFF auf, die dann serverseitig das Gateway ansprechen. Siehe API & Gateway zum Protokoll.

Nutzer sehen nur ihre eigenen Gilden

Beim Auflisten der Server liefert das Gateway nur Gilden zurück, in denen der Nutzer tatsächlich Mitglied ist (oder in denen er Bot-Owner ist). Selbst innerhalb eines Gilden-Kontexts kann ein eingeloggter Nicht-Mitglied die Daten dieser Gilde nicht lesen: Der Server erzwingt für jeden gildenbezogenen Call mindestens guild_member, sodass ein manipuliertes guild_id keinen fremden Server-Inhalt leaken kann.

Berechtigungsstufen

Jeder Beitrag (Widget, Panel, Liste, Seite) und jede privilegierte RPC-Methode deklariert eine Mindeststufe. Das Gateway leitet die effektive Stufe des Nutzers aus Reds eigenem Berechtigungssystem ab und erzwingt sie serverseitig bei jedem Call – das Frontend-Filtering dient nur der UX.

Stufe Wert Auf Red gemappt
authenticated 0 Via Discord OAuth2 eingeloggt
guild_member 1 Mitglied der Gilde
guild_mod 2 Reds Mod-Rolle (bot.is_mod)
guild_admin 3 Reds Admin-Rolle oder Discord-manage_guild
guild_owner 4 guild.owner_id == user.id
bot_owner 5 bot.is_owner(user)

Die Stufen sind kumulativ: Eine höhere Stufe erfüllt jede niedrigere Anforderung. Das Mapping liegt in der permissions.py des Cogs.

Sicherheitsmodell in einem Bild

        Geheimnisse hier ─┐
                          ▼
Browser ──OAuth2──▶ BFF (SvelteKit-Server) ──Token──▶ Gateway (localhost) ──▶ Red-Bot
  Cookie (HMAC)          DISCORD_CLIENT_SECRET           compare_digest          is_owner / is_admin / …
                         GATEWAY_TOKEN                                           Permission-Recheck
                         SESSION_SECRET
  • Discord-Client-Secret, Gateway-Token und Session-Secret liegen nur im BFF.
  • Der Browser hält nur ein signiertes Cookie – kein nutzbares Geheimnis.
  • Berechtigungen werden am Bot erzwungen, nicht dem Frontend geglaubt.

Verwandte Seiten

  • KonfigurationSESSION_SECRET, GATEWAY_TOKEN und die OAuth2-Variablen
  • API & Gateway – wie der BFF das Gateway aufruft und wo Rechte geprüft werden
  • Architektur – das BFF-Muster im Detail

Clone this wiki locally