ÜAuth – zentrale Authentifizierungs- und Tokenschicht
Ausgangslage
- Minecraft-Clients authentifizieren sich heute nur gegenüber Microsoft/DevAuth. Die Übliche-Server erkennen die Spieler zwar, geben aber kein nach außen verwendbares Token aus.
- REST-Endpunkte (z. B.
/api/profile/personal-totem) erwarten Dashboard-JWTs. Ein Minecraft-Client kann diese nicht erzeugen; jede Mod müsste eine Web-Login-Logik kopieren. - Verschiedene Mods/Tools (Totem, Editor-Client, zukünftige QoL-Mods) duplicieren HTTP-Auth-Code oder meiden die APIs ganz.
Ziele
- Einheitliche JWT-Ausstellung für alle Übliche-Dienste (Minecraft-Mods, Web, Tools).
- Token-Laufzeit, Scopes und Widerruf zentral steuern.
- Zero-Login im Client: beim Join erhält der Spieler automatisch ein gültiges Token.
- Optional: Weiterverwendung desselben Tokens im Browser (z. B. Profile-Seite per Link öffnen und bereits eingeloggt sein).
Anforderungen & Randbedingungen
- Issuer: neuer Auth-Service („ÜAuth“) innerhalb des Plattform-Stacks, zuständig für Signatur/Validierung.
- Tokenformat: JWT (RS256), Claims mindestens
sub(User UUID),usr(name),scopes,iat,exp. - Scopes: granular (z. B.
totem:write,profile:read,inventory:manage) damit Mods nur benötigte Rechte erhalten. - Lebensdauer: kurzlebige Access Tokens (z. B. 30 min) + optional Refresh Token (24 h) für Clients, die nicht jedes Mal joinen können.
- Transport: HTTPS,
Authorization: Bearer <jwt>. - Backwards-Kompatibilität: dashboard-JWTs können weiterhin akzeptiert werden, solange Signatur/Issuer stimmt.
Architekturüberblick
Komponenten
- ÜAuth Service
- REST-Endpunkte:
POST /auth/session/minecraft→ nimmtmcUuid,nonce,signatureund stellt Access/Refresh aus.POST /auth/token→ regulärer OAuth2-like Refresh.GET /.well-known/jwks.json→ Schlüsselverteilung.
- Speichert ausgehändigte Tokens (für Widerruf) und verwaltet Scope-Mapping.
- REST-Endpunkte:
- Minecraft-Server Hook
- Beim erfolgreichen Login erzeugt er ein Kurzzeit-Nonce (z. B. 60 s gültig), signiert mit Server-Key.
- Sendet Nonce + PlayerUUID zum Client über Custom Payload.
- Client Auth Library (Fabric/Forge)
- Empfangt Nonce, ruft
POST /auth/session/minecraftauf, gibt Nonce + eigene Microsoft Session Signatur weiter. - Cachet Access/Refresh Token (verschlüsselt in
~/.uebliche/tokens.json). - Stellt Utilitys für HTTP-Requests bereit (z. B.
AuthorizedHttpClient#get(path, scope)).
- Empfangt Nonce, ruft
- Verbrauchende Mods
- Registrieren benötigte Scopes beim Start.
- Nutzen Library, kein eigener Token- oder Upload-Code notwendig.
Flows
- Minecraft Join
- Spieler verbindet sich mit Übliche-Server → AuthHook erstellt Nonce.
- Client empfängt Nonce + Endpoint-URL.
- Client ruft
POST /auth/session/minecraftmit Payload{ uuid, nonce, ms_sign, requested_scopes }. - ÜAuth validiert Nonce (von Server signiert) + Microsoft Signatur, stellt JWT + Refresh aus.
- Client informiert Mods, dass Token verfügbar ist.
- Web Single-Sign-On (optional)
- Mod öffnet Browser mit
https://uebliche.net/profile?token=<jwt>; Website akzeptiert Token, setzt eigenes Cookie.
- Mod öffnet Browser mit
- Refresh
- Client ruft
POST /auth/tokenmit Refresh Token, erhält neues Access Token ohne erneuten Join.
- Client ruft
Änderungen im Code
Server
- Neuer Dienst (Spring/Quarkus o. ä.) oder Erweiterung im vorhandenen Platform-Service.
- Konfiguration für JWKS/Keys, Scopes, TTL, Rate Limits.
- Minecraft-Server Modul, das Nonces ausstellt (z. B.
AuthHandshakeListener):javarecord NoncePayload(UUID playerId, Instant issuedAt, byte[] signature) {}
Client
- Neues Modul
mods/common-auth(Gradle Subproject) mit:AuthManager(Token State Machine).HttpClientmit Auto-Retry und Scope-Prüfung.- Fabric/Forge Hooks (
ClientPlayNetworking) zum Empfang des Nonce-Payloads.
- Totem-Mod ersetzt direkten Hinweis auf Webprofil:
- Wenn Token vorhanden → In-Game-UI lädt/aktualisiert Totem via API.
- „Im Browser öffnen“ Button hängt JWT als Query an, sodass Webseite schon eingeloggt ist.
Fahrplan
- PoC ÜAuth Service
- Minimal: In-Memory Nonce Store, statischer Key, simple scope-liste.
- Endpunkt
POST /auth/session/minecraft+ JWKS.
- Minecraft-Server Hook
- Custom Payload
uebliche:auth_nonce.
- Custom Payload
- Auth Client Library
- Token-Anfrage, Storage, HTTP-Helper.
- Totem Integration
- UI + Uploads über neues Token.
- Rollout auf weitere Mods
- Editor-Client, Monitoring, ggf. Dev-Tools.
- Production Hardening
- Key-Rotation, Revocation-List, zentraler Audit-Log.
Konkreter Implementierungsplan (Iteration 1)
| Schritt | Teil | Details |
|---|---|---|
| 1 | Server: Nonce-Payload | - Neues Paket net.uebliche.features.auth.handshake.- Listener auf PlayerLoginEvent generiert AuthNonce (UUID nonceId, Instant issuedAt, byte[] signature).- Überträgt Payload via übliche:auth/nonce (Minestom Custom Channel).- Signatur = HMAC256( nonceId + playerUuid + issuedAt, JWT_SECRET). |
| 2 | Server: REST-Endpoint | - POST /auth/session/minecraft (Javalin Route unter AuthService).- Request { "playerId": "<uuid>", "nonceId": "<uuid>", "signature": "<base64>", "scopes": ["totem:write"] }.- Prüft Nonce (existiert, max 60 s alt, nicht verbraucht). - Stellt Access (30 min) + Refresh (24 h) aus ( AuthToken Sammlung wiederverwenden, tokenType=MCAUTH).- Response { accessToken, expiresIn, refreshToken, refreshExpiresIn }. |
| 3 | Client-Library (Fabric) | - neues Modul mods/lib-auth mit Singletons AuthState, AuthHttpClient.- Packet Handler auf übliche:auth/nonce: ruft HTTPS Endpoint auf, speichert Tokens unter %AppData%/.uebliche/tokens.json (verschlüsselt mit Windows DPAPI / SecretKeySpec).- Exponiert AuthState.requireScope("totem:write") → sorgt dafür, dass Access vorhanden ist (ggf. refresh). |
| 4 | Totem-Mod Integration | - beim Start AuthState.onAvailable(token -> personalTotemClient.setAuthorization(token)).- Upload UI (nachgelagert) nutzt Library statt Browser. |
| 5 | Fallback | - Falls Token nicht beschaffbar (z. B. Offline), UI zeigt Hinweis + weiterhin Browser-Link. |
Datenmodell-Erweiterungen
AuthTokenerhält Feldorigin(DASHBOARD,MC_SESSION) undscopes.- Mongo-Index
(userId, origin, scopesHash). - Neue Collection
AuthNonce(TTL 2 Minuten) oder ReuseSignInCodemit speziellem Typ.
Sicherheit
- Nonces einmalig, expire nach 60 s.
- Server signiert Nonce → Client kann nicht selbst Nonce bauen.
- HTTPS erzwingen (dev/staging: env-Flag zum Zulassen von
http://localhost). - Refresh Token verschlüsselt abgelegt; bei Verlust
AuthService.revokeAll(userId).
Offene Punkte
- Key-Verteilung für Mods →
mod-templateerhältauthGradle dependency + env varUEB_AUTH_ENDPOINT. - Browser-SSO: separate Route
GET /auth/web-login?token=...(optional in Iteration 2). - Forge-Port: analoger Packet-Handler in
loader-forge.
Mit dieser Basis können alle Übliche-Mods denselben JWT verwenden; spätere Erweiterungen (Web SSO, externe Tools) profitieren ebenfalls. Bitte Feedback, bevor ich mit Implementierung von Schritt 1 beginne.