05 · Token-Prüfung und Sicherheit
Ob Push oder Pull – am Ende erhalten Entwickler:innen stets ein wsa (HS256-JWT). Dieser Artikel ist Pflichtlektüre für alle Integrator:innen – eine unzureichende Prüfung = Identität ist fälschbar.
Verpflichtende Prüf-Checkliste
Nach dem Erhalt des wsa prüfen Sie im Backend-Dienst der Erweiterungs-App der Reihe nach (verifyWsa hat alles integriert):
- Signatur: Mit dem von der Plattform verteilten/bei der Registrierung erhaltenen Schlüssel per HS256 prüfen. Fehlschlag → ablehnen.
exp: Aktuelle Zeit ≤exp(inkl. geringer Leeway).expmuss vorhanden sein – ein Token ohneexpsollte direkt abgelehnt werden (andernfalls läuft es nie ab).iss: Muss gleichgptbots-workspacesein.aud: Muss gleich dem Host der Ziel-Erweiterungs-App sein. Dies ist die entscheidende Abwehrlinie gegen „Token wird gestohlen und gegen eine andere App eingesetzt" und darf nicht weggelassen werden.iat/nbf(falls vorhanden): Dürfen nicht in der Zukunft liegen (über die Leeway hinaus), um zu verhindern, dass ein Token mit „Ausstellungszeitpunkt in ferner Zukunft" langfristig gültig ist.- Mandantentrennung per
workspace_id: Hat die Erweiterung eine Isolation über mehrere Workspaces umgesetzt, ordnen Sie die Anfrage diesemworkspace_idzu und verbieten Sie mandantenübergreifende Zugriffe. - Nach dem Landen sofort das
wsa/codeaus der URL entfernen:history.replaceState, um zu vermeiden, dass Nutzer:innen beim Kopieren der URL das Token mitteilen. - Eigene Session aufbauen: In eine app-eigene Session/Cookie umwandeln; nachfolgende Anfragen sollten sich nicht mehr auf das
wsastützen – es läuft nach 5 Minuten ab.
Das
verifyWsades offiziellen SDK verlangt zwingend das Vorhandensein vonexp, prüftiat/nbfauf Zukunftsdrift und führt einen Signaturvergleich in konstanter Zeit sowie eine Algorithmus-Whitelist durch (standardmäßig nurHS256, umalg-Verwirrungsangriffe auszuschließen). Wer es verwendet, erfüllt automatisch 1–5.
Prüfung mit dem SDK empfohlen
import { verifyWsa, WsaVerificationError } from '@gptbots/workspace-extension-verify';
try {
const id = verifyWsa(wsa, {
secret: process.env.EXTENSION_APP_SECRET,
audience: 'app.example.com',
});
// id: { accountId, role, workspaceId, username?, email?, avatar?, appName?, issuedAt?, expiresAt? }
} catch (e) {
if (e instanceof WsaVerificationError) {
// e.code: InvalidToken | InvalidSignature | Expired | NotYetValid
// | WrongIssuer | WrongAudience | MissingClaim | UnsupportedAlgorithm
}
}
Vollständige Optionen und Fehlercodes siehe SDK-API-Referenz.
Prüfung ohne SDK (mehrere Sprachen)
Das wsa ist ein standardmäßiges HS256-JWT, das jede JWT-Bibliothek prüfen kann. Aktivieren Sie unbedingt explizit die iss- / aud-Prüfung und fixieren Sie algorithms=['HS256'].
Java (auth0 java-jwt)
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SHARED_SECRET))
.withIssuer("gptbots-workspace")
.withAudience("app.example.com")
.acceptLeeway(30) // 30s Uhrenabweichung tolerieren
.build();
DecodedJWT jwt = verifier.verify(wsaParam);
String userId = jwt.getSubject();
String workspaceId = jwt.getClaim("workspace_id").asString();
String role = jwt.getClaim("role").asString();
String username = jwt.getClaim("username").asString(); // kann null sein
String email = jwt.getClaim("email").asString(); // kann null sein
Node.js (jsonwebtoken)
const jwt = require('jsonwebtoken');
const payload = jwt.verify(wsaParam, SHARED_SECRET, {
algorithms: ['HS256'],
issuer: 'gptbots-workspace',
audience: 'app.example.com',
clockTolerance: 30,
});
const { sub: userId, workspace_id, role, username, email, avatar } = payload;
Python (PyJWT)
import jwt
payload = jwt.decode(
wsa_param,
SHARED_SECRET,
algorithms=["HS256"],
issuer="gptbots-workspace",
audience="app.example.com",
leeway=30,
)
user_id = payload["sub"]
workspace_id = payload["workspace_id"]
role = payload["role"]
Hinweis zur Schlüsselkodierung: HS256 verwendet die Schlüsselzeichenkette direkt als UTF-8-Bytes als HMAC-Key. Der per-App-Schlüssel von Tier 2 hat die Form
wext_+64 hex; übergeben Sie ihn bitte als unveränderte Zeichenkette als Schlüssel (keine erneute Hex-Dekodierung), konsistent zur Signaturseite der Plattform.
Sicherheitsanforderungen (Punkt für Punkt umsetzen)
- Der Schlüssel ist das gesamte Sicherheitsmodell. Das aktuelle HS256 ist ein symmetrischer Schlüssel: Einmal geleakt, kann jede:r beliebige Workspace-Nutzeridentitäten fälschen und in die angebundene Erweiterungs-App eindringen. Nur im Backend halten (Umgebungsvariablen/KMS), niemals in Frontend-Code, Git-Repository, Logs oder Client-Konfiguration schreiben.
- Exposition des JWT in der URL (nur Push): Der Query-String wird in Browser-Verlauf, Access-Logs von Webservern, CDN-Cache-Logs und Referer-Einträgen erfasst. Selbst wenn erfasst, ist es innerhalb von 5 Minuten weiterhin nutzbar. Nach dem Landen sofort mit
history.replaceStateentfernen (consumeHandoffmacht dies standardmäßig). Pull (M-Auth) legt daswsavon Natur aus nicht in die URL und ist sicherer. - Das
wsanicht an Unterressourcen weiterreichen. Nach dem Umwandeln in die eigene Session tragen nachfolgende XHR/fetch/img das rohewsagrundsätzlich nicht mehr mit, sonst erscheint es im Referer jeder Unterressource. - Uhrensynchronisation. HS256 bewertet
expstreng; die Serveruhr muss per NTP synchronisiert sein; im Beispiel toleriert die 30s-leewayeine geringe Abweichung, weiten Sie sie nicht auf Minuten aus. rolenur als Standard-Berechtigungszuordnung. Es spiegelt nur die Rolle der Nutzer:innen in diesem Workspace wider, nicht die Berechtigung innerhalb Ihrer App; Ihre App pflegt ihr eigenes Berechtigungsmodell.- Mandantentrennung. Verwenden Sie stets
workspace_idals Datentrennungsschlüssel, um zu verhindern, dass Nutzer:innen aus Workspace A Daten von B lesen. - Notfall bei Schlüsselrotation/-widerruf: „Schlüssel rotieren" für die App in der Space-Verwaltung – es wird ein neuer Schlüssel generiert und einmalig angezeigt; konfigurieren Sie anschließend Ihr Backend mit dem neuen Schlüssel neu.
5. Vertrauensgrenze des Frontends (wichtig)
- Das Frontend dient nur als Anzeige-Platzhalter, nicht für Autorisierungsentscheidungen. Das Frontend kann den Payload des JWT per base64 öffnen, aber ohne Schlüssel kann die Signatur nicht geprüft werden – jede:r kann einen „scheinbar korrekten" Payload fälschen.
- Alle Entscheidungen darüber, „wer diese Person ist und ob sie etwas tun darf", müssen sich nach dem Ergebnis von
verifyWsaim Backend der Erweiterungs-App richten. - Die Standardstrategie lautet daher: Das Frontend übergibt das
wsa/codean das Backend der Erweiterungs-App → das Backend prüft → das Backend baut eine Session auf → das Frontend akzeptiert nur diese Session.
Nächster Schritt: SDK-API-Referenz für die vollständige API; bei Problemen konsultieren Sie bitte Fehlerbehebung.
