SDK-API-Referenz
Die offiziellen SDKs sind zwei framework-unabhängige Pakete ohne Laufzeitabhängigkeiten; den Quellcode erhalten Sie auf GitHub unter: https://github.com/gptbots/workspace-extension-sdk.
| Paketname | Laufort | Einstiegspunkte |
|---|---|---|
@gptbots/workspace-extension-verify |
Backend (Node ≥ 18) | verifyWsa, exchangeWorkspaceCode |
@gptbots/workspace-extension-sdk |
Browser | consumeHandoff, startWorkspaceLogin, completeWorkspaceLogin … |
Beide Pakete sind ESM (
"type": "module"). Verwenden Sie in CommonJS-Projekten ein dynamischesimport()oder wechseln Sie zu ESM.
Backend-Paket @gptbots/workspace-extension-verify
verifyWsa(token, options): WorkspaceIdentity
Prüft das wsa und gibt die Workspace-Identität zurück. Prüfreihenfolge: Signatur → iss → aud → Ablauf (exp±leeway, inkl. iat/nbf) → Pflichtangaben.
interface VerifyOptions {
secret?: string; // HS256-Schlüssel (per-App oder geteilt). Bei HS256-Prüfung erforderlich
publicKey?: string; // RS256-PEM-Public-Key. Bei RS256-Prüfung erforderlich (Roadmap)
audience: string; // Erweiterungs-App-Host, muss gleich dem Token-aud sein (erforderlich)
issuer?: string; // Standard 'gptbots-workspace'
leewaySeconds?: number; // Toleranz für Uhrenabweichung (Sekunden), Standard 30
algorithms?: ('HS256' | 'RS256')[]; // Standard ['HS256']
}
interface WorkspaceIdentity {
accountId: string; // = JWT sub
role: 'OWNER' | 'ADMIN' | 'MEMBER'; // unbekannte Werte werden zu MEMBER normalisiert
workspaceId: string; // = JWT workspace_id
username?: string; email?: string; avatar?: string; appName?: string;
issuedAt?: number; // = iat (Sekunden)
expiresAt?: number; // = exp (Sekunden)
}
expverpflichtend: fehlend oder keine endliche Zahl → wirftMissingClaim(wird nicht als „läuft nie ab" behandelt).iat/nbf(falls vorhanden) in der Zukunft über die Leeway hinaus → wirftNotYetValid.- Bei Fehlschlag wird
WsaVerificationErrorgeworfen (mit.code); bei einer Fehlkonfiguration der aufrufenden Seite (z. B. fehlender Schlüssel) wirdTypeErrorgeworfen.
Werte von WsaVerificationError.code:
| code | Bedeutung |
|---|---|
InvalidToken |
Token leer / strukturell ungültig / segment ist kein JSON-Objekt |
InvalidSignature |
Signatur stimmt nicht (falscher Schlüssel, manipuliert) |
Expired |
Abgelaufen (vor exp + leeway) |
NotYetValid |
iat/nbf in der Zukunft (über die Leeway hinaus) |
WrongIssuer |
iss ≠ erwarteter Wert |
WrongAudience |
aud ≠ Ihre audience |
MissingClaim |
Fehlendes exp / sub / role / workspace_id |
UnsupportedAlgorithm |
alg nicht in der Whitelist (standardmäßig nur HS256) |
exchangeWorkspaceCode(options): Promise<WorkspaceCodeExchangeResult>
Für den Pull-Login: im Backend der Erweiterungs-App den einmaligen code + PKCE-codeVerifier gegen ein wsa eintauschen. Auf keinen Fall im Browser aufrufen.
interface ExchangeWorkspaceCodeOptions {
tokenUrl: string; // /token-Endpunkt der Plattform (absolute URL)
code: string; // der beim Callback erhaltene einmalige Autorisierungscode
codeVerifier: string; // der zum code_challenge passende PKCE-verifier
fetch?: typeof fetch; // injizierbares fetch (Tests/alte Laufzeiten); Standard globales fetch
timeoutMs?: number; // Anfrage-Timeout, Standard 10000; 0 zum Deaktivieren übergeben
}
interface WorkspaceCodeExchangeResult {
wsa: string; // das signierte wsa, an verifyWsa übergeben
tokenType?: string; // 'Bearer'
expiresIn?: number; // Gültigkeit des wsa (Sekunden)
}
- Übertragungsfehler / non-2xx / Business-
code≠0(z. B.403209 invalid_grant,403210 invalid_verifier) / fehlendesdata.wsa→ wirftError. - Timeout wirft
token exchange timed out after <ms>ms(Standard 10s, verhindert, dass eine langsame Plattformantwort Ihr Backend blockiert).
Beispiel für eine Express-Middleware
import { verifyWsa, WsaVerificationError } from '@gptbots/workspace-extension-verify';
export function requireWorkspaceIdentity(secret: string, audience: string) {
return (req, res, next) => {
try {
req.identity = verifyWsa(req.body.wsa, { secret, audience });
next();
} catch (e) {
const code = e instanceof WsaVerificationError ? e.code : 'Error';
res.status(401).json({ code });
}
};
}
Browser-Paket @gptbots/workspace-extension-sdk
Push (Push handoff)
readHandoffToken(search?, paramName?): string | null
Reine Funktion, liest das rohe wsa aus dem Query-String. search standardmäßig location.search, paramName standardmäßig 'wsa'.
stripHandoffToken(paramName?, ctx?): void
Entfernt mit history.replaceState das wsa aus der aktuellen URL, damit es nicht in Adressleiste/Verlauf/Referer zurückbleibt. Außerhalb des Browsers eine sichere No-Op. ctx?: { history?, location? } kann injiziert werden (Tests).
consumeHandoff(options): Promise<WorkspaceIdentity>
Bequemer Ablauf der use-Stufe: wsa lesen → POST an das Backend der Erweiterungs-App → nach Erfolg das wsa entfernen → Identität zurückgeben.
interface ConsumeHandoffOptions {
exchangeUrl: string; // Backend-Prüfschnittstelle der Erweiterungs-App
fetch?: typeof fetch; // injizierbar
search?: string; // Standard location.search
paramName?: string; // Standard 'wsa'
strip?: boolean; // Standard true (nur bei Erfolg entfernen)
}
Das Token wird nur nach erfolgreichem Austausch entfernt, damit ein vorübergehender Fehler durch Neuladen erneut versucht werden kann. Soll es auch bei Fehlschlag sofort entfernt werden, im
catchmanuellstripHandoffToken()aufrufen.
Pull (Pull / M-Auth)
startWorkspaceLogin(options): Promise<WorkspaceLoginRequest>
Generiert PKCE, speichert im sessionStorage, baut die URL auf und (standardmäßig) leitet zu /authorize weiter. Erfordert einen sicheren Kontext (HTTPS/localhost).
interface StartWorkspaceLoginOptions {
authorizeUrl: string; // /authorize-Endpunkt der Plattform (absolute URL)
clientId: string; // app home URL der Erweiterungs-App
redirectUri: string; // Callback-Adresse, host muss dieselbe Domain wie clientId haben
state?: string; // standardmäßig automatisch generierter 16-Byte-Zufalls-CSRF-state
workspaceId?: string; // vorausgewählter Workspace, überspringt die Organisationsauswahlseite
storage?: StorageLike; // Standard sessionStorage
redirect?: (url: string) => void; // Standard location.assign
navigate?: boolean; // false = nur URL bauen, nicht weiterleiten (popup/Tests)
}
interface WorkspaceLoginRequest { url: string; state: string; codeVerifier: string; }
readAuthorizeCallback(search?, storage?): AuthorizeCallback | null
Auf der Callback-Landingpage: liest code + state, prüft state (CSRF), gibt code + den gespeicherten codeVerifier zurück. Konsumiert die gespeicherte Anfrage nicht (das Konsumieren wird bis zum erfolgreichen Austausch verzögert), damit ein vorübergehender Fehler durch Neuladen erneut versucht werden kann. Gibt null zurück, wenn kein code und kein error vorhanden ist.
interface AuthorizeCallback { code: string; state: string | null; codeVerifier: string; }
stripAuthorizeCallback(ctx?): void
Entfernt code / state aus der aktuellen URL.
completeWorkspaceLogin(options): Promise<WorkspaceIdentity>
Bequemer Ablauf der use-Stufe: Callback lesen und prüfen → POST {code, codeVerifier} an Ihr Backend → nach Erfolg die URL bereinigen → Identität zurückgeben.
interface CompleteWorkspaceLoginOptions {
exchangeUrl: string; // Ihre eigene Backend-Austauschschnittstelle
fetch?: typeof fetch;
search?: string; // Standard location.search
storage?: StorageLike; // Standard sessionStorage
strip?: boolean; // Standard true
}
Werte von WorkspaceLoginError.code
| code | Bedeutung |
|---|---|
NoCallback |
Kein Autorisierungscode in der URL |
MissingRequest |
Keine/beschädigte gespeicherte Anmeldeanfrage (zuerst startWorkspaceLogin aufrufen) |
StateMismatch |
state-CSRF-Prüfung fehlgeschlagen |
AuthorizeError |
Callback ist eine OAuth-Fehlerweiterleitung (?error=...) |
NoFetch |
Keine verfügbare fetch-Implementierung |
ExchangeFailed |
Austauschschnittstelle liefert non-2xx |
InvalidResponse |
Austauschschnittstelle liefert ungültiges JSON |
CryptoUnavailable |
Kein Web Crypto (erfordert sicheren Kontext HTTPS/localhost) |
StorageUnavailable |
Kein sessionStorage (PKCE-verifier kann nicht gespeichert werden) |
InvalidAuthorizeUrl |
authorizeUrl ist keine absolute URL |
Drittens: Lokale Installation aus dem Archiv
unzip workspace-extension-sdk-0.1.0.zip
# Beide Pakete sind bereits mit dist vorgebaut (main=dist/index.js, types=dist/index.d.ts)
npm i ./workspace-extension-sdk/packages/verify # Backend
npm i ./workspace-extension-sdk/packages/browser # Frontend
Falls Sie selbst bauen / Tests ausführen möchten:
cd workspace-extension-sdk
npm install
npm run build # tsc → dist je Paket
npm test # node --test (keine externen Testabhängigkeiten, benötigt Node ≥ 22.6 zum direkten Ausführen von .ts)
npm run type-check # tsc --noEmit
