> This page is for Plattform, version V4 (default).
> For other versions, use one of these documentation indexes:
> - V4 (default): https://next.developer.frame.io/platform/v4/llms.txt
> - V4 Experimental: https://next.developer.frame.io/platform/v4-experimental/llms.txt
> - Vorgängerversion: https://next.developer.frame.io/platform/v2/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://next.developer.frame.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://next.developer.frame.io/_mcp/server.

# TypeScript SDK in Frame.io – Authentifizierungsleitfaden

In diesem Leitfaden wird erklärt, wie Sie sich mit der Frame.io-API über das **TypeScript SDK in Frame.io** (`frameio`) authentifizieren.In der Frame.io V4-API wird der [Adobe Identity Management Service (IMS)](https://developer.adobe.com/developer-console/docs/guides/authentication/) genutzt, die OAuth-2.0-Identitätsplattform von Adobe.Dies ist eine eigenständige Referenz für TypeScript-/JavaScript-Entwickelnde.Alle unten stehenden Codebeispiele und Flüsse gelten ausschließlich für das `frameio`-Paket.

---

## Authentifizierungstypen im TypeScript SDK

Im TypeScript SDK werden vier OAuth-Authentifizierungsklassen plus die direkte Token-Nutzung unterstützt:

| Methode                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Anwendungsfall                                                         | Benutzendeninteraktion? | Clientschlüssel erforderlich? |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ----------------------- | ----------------------------- |
| **Statischer Token**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | Schnelle Skripts, Tests oder Sie haben bereits einen Token             | Nein                    | Nein                          |
| **Server-zu-Server**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | Backend-Services, Cron-Jobs, Automatisierung                           | Nein                    | Ja                            |
| **Web-Programm**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | Serverseitige Apps (Express, Fastify, Next.js)                         | Ja                      | Ja                            |
| **SPA (PKCE)**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | Browser-Apps, in denen kein Schlüssel gespeichert werden kann          | Ja                      | Nein                          |
| **Native App (PKCE)**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | Desktop- oder mobile Apps mit selbstdefinierten URI-Schema-Umleitungen | Ja                      | Nein                          |
| Durch **Server-zu-Server** kann Ihre App als Dienstkonto ohne Benutzendeninteraktion genutzt werden.Diese Funktion ist nur für Frame.io V4-Konten verfügbar, die über die [Adobe Admin Console](https://adminconsole.adobe.com/) verwaltet werden.Durch **Web App** und **SPA** kann Ihre App als bestimmter Benutzer bzw. bestimmte Benutzerin fungieren.Bei beiden wird im Hintergrund Adobe IMS verwendet: Benutzende autorisieren Ihre App, und der resultierende Code wird vom SDK gegen Token eingetauscht.Der `/authorize/v2`- und `/token/v3`-Fluss von IMS wird vom TypeScript SDK übernommen. Für Web-Anwendungen benötigen Sie einen Clientschlüssel; für SPA verwenden Sie stattdessen [PKCE](https://datatracker.ietf.org/doc/html/rfc7636).**Native App** folgt demselben PKCE-Fluss wie SPA, verwendet aber die `adobe+<hash>://callback</hash>` Umleitungs-URI, die Ihren Native App-Anmeldedaten von Adobe zugewiesen wird. Dadurch kann die Umleitung nach der Autorisierung auf Betriebssystemebene von Ihrer Anwendung abgefangen werden. |                                                                        |                         |                               |

---

## Dienstkonto-User

Bei der Server-zu-Server-Authentifizierung fungiert Ihre Anwendung als **Dienstkonto-User**, ein spezieller Kontotyp, mit dem im Namen des Services Aktionen durchgeführt werden können.Diese sind für andere Benutzende in Frame.io sichtbar: Wenn eine Aktion von einem Dienstkonto durchgeführt wird, wird dessen Name in der Bedienoberfläche angezeigt.Sie können dem Dienstkonto über die [Adobe Admin Console](https://adminconsole.adobe.com/) und die [Developer Console](https://developer.adobe.com/console) Zugriff gewähren und diesen widerrufen.Die Namen von Dienstkonten werden über die Frame.io-Bedienoberfläche verwaltet.Standardmäßig heißt Ihre erste S2S-Verbindung **Dienstkonto-User**, die zweite **Dienstkonto-User 2** und so weiter.

> **Info**
>
> Weitere Informationen finden Sie unter [Automatisieren Ihres Setups mit der Server-zu-Server-Unterstützung von Frame.io](https://helpx.adobe.com/enterprise/using/automate-using-frame-io.html).

---

## Schnellstart

### Voraussetzungen

1. **Anmeldedaten** von der [Adobe Developer Console](https://developer.adobe.com/console):

* **Client-ID** – für alle OAuth-Flüsse erforderlich - **Clientschlüssel** – für Server-zu-Server- und Web-Anwendungsflüsse erforderlich - **Umleitungs-URI** – für Web-Anwendungs-, SPA- und native Anwendungsflüsse erforderlich; muss in Ihrem Adobe-Projekt registriert sein

2. **SDK installieren:**

```bash
npm install frameio
```

### Auswählen einer Methode

* \*\*Keine Benutzenden beteiligt?\*\*Verwenden Sie **Server-zu-Server** (`ServerToServerAuth`).
* \*\*Benutzende beteiligt und Sie können einen Schlüssel speichern?\*\*Verwenden Sie **Web-Anwendung** (`WebAppAuth`).
* \*\*Benutzende beteiligt, aber Sie können keinen Schlüssel speichern?\*\*Verwenden Sie bei Browser-Anwendungen **SPA** (`SPAAuth`) und bei Desktop- oder mobilen Anwendungen **Native App** (`NativeAppAuth`).

---

## Zugriffstoken

Falls Sie bereits über einen Zugriffstoken verfügen (aus einem anderen OAuth-System oder von einem vorherigen Austausch, z. B. über unseren [API-Explorer](/platform/api-reference/accounts/index?explorer=true)), können Sie ihn direkt übergeben:

```typescript
import { FrameioClient } from "frameio";

const client = new FrameioClient({ token: "YOUR_ACCESS_TOKEN" });
```

Dies ist die einfachste Herangehensweise, aber der Token wird letztendlich ablaufen und wird nicht vom SDK aktualisiert.

### Ältere Entwicklungstoken

Bei V4-migrierten Konten, die noch nicht über die [Adobe Admin Console](https://adminconsole.adobe.com/) verwaltet werden, können Sie weiterhin ältere Entwicklungstoken von der [Frame.io-Entwickelnden-Website](https://developer.frame.io/app/tokens) verwenden.Sie müssen den Header `x-frameio-legacy-token-auth` einbeziehen und auf `true` setzen:

```typescript
import { FrameioClient } from "frameio";

const client = new FrameioClient({
    token: "YOUR_LEGACY_DEVELOPER_TOKEN",
    headers: { "x-frameio-legacy-token-auth": "true" },
});
```

Ältere Entwicklungstoken laufen nicht ab, sind aber ein Übergangsmechanismus.Für neue Integrationen und Produktionskapazität empfehlen wir die Verwendung einen der unten stehenden OAuth-2.0-Flüsse.Weitere Details finden Sie im [Migrationsleitfaden](/platform/docs/resources/migration#authentication).

---

## Server-zu-Server (Client-Anmeldedaten)

Verwenden Sie dies für Backend-Services und Skripte, die Zugriff auf Frame.io ohne Benutzendeninteraktion benötigen.Dieser Fluss ist nur für Frame.io V4-Konten verfügbar, die über die [Adobe Admin Console](https://adminconsole.adobe.com/) verwaltet werden.Deine Anwendung wird ohne menschliche Eingriffe als [Dienstkonto-User](#service-account-users) authentifiziert.

```typescript
import { FrameioClient, ServerToServerAuth } from "frameio";

const auth = new ServerToServerAuth({
    clientId: "YOUR_CLIENT_ID",
    clientSecret: "YOUR_CLIENT_SECRET",
});

const client = new FrameioClient({ token: () => auth.getToken() });
```

Das ist alles.`auth.getToken()` ist eine asynchrone Funktion, die bei jeder Anfrage vom SDK aufgerufen wird.Wenn der aktuelle Token noch gültig ist, wird er sofort zurückgegeben.Wenn er kurz vor dem Ablauf steht, wird zuerst ein neuer Token abgerufen, völlig transparent.

### So funktioniert es

Ihre Client-Anmeldedaten (Client-ID und Schlüssel) **laufen niemals ab**.Sie rotieren sie lediglich manuell, aus Sicherheitsgründen.Durch S2S haben Sie praktisch permanenten, ununterbrochenen API-Zugriff ohne manuelle Eingriffe.

Unter der Haube:

1. Beim ersten API-Aufruf wird von `getToken()` mithilfe des `client_credentials`-Grant ein neues Zugriffstoken von Adobe IMS angefordert.
2. Der Token wird im Arbeitsspeicher zwischengespeichert.Einzelne Zugriffstoken laufen ab (in der Regel nach 24 Stunden), aber das wird für Sie gehandhabt.
3. Wenn ein zwischengespeicherter Token innerhalb des Aktualisierungspuffers liegt (Standard: 60 Sekunden vor Ablauf), wird vom SDK mit denselben Client-Anmeldedaten automatisch ein neuer abgerufen.
4. Es sind keine Aktualisierungstoken beteiligt.Die Client-Anmeldedaten selbst sind das langlebige Geheimnis, und sie können immer verwendet werden, um einen neuen Zugriffstoken zu prägen.

### Explizite Authentifizierung

Wenn Sie den Token frühzeitig abrufen möchten (zum Beispiel, um beim Start schnell mit ungültigen Anmeldedaten zu scheitern):

```typescript
const auth = new ServerToServerAuth({ clientId: "...", clientSecret: "..." });
await auth.authenticate(); // throws AuthenticationError if credentials are invalid
const client = new FrameioClient({ token: () => auth.getToken() });
```

---

## Web-Anwendung (Autorisierungscode)

Eignet sich für serverseitige Anwendungen, bei denen sich Benutzende mit ihrer Adobe ID anmelden.Für diesen Fluss ist ein Clientschlüssel erforderlich, der sicher auf Ihrem Server gespeichert werden muss.

#### Benutzende an Adobe IMS umleiten

```typescript
    import { WebAppAuth } from "frameio";
    import crypto from "crypto";

    const auth = new WebAppAuth({
        clientId: "YOUR_CLIENT_ID",
        clientSecret: "YOUR_CLIENT_SECRET",
        redirectUri: "https://yourapp.com/callback",
    });

    // Generate a cryptographically random state value to prevent CSRF attacks
    const state = crypto.randomBytes(32).toString("hex");

    const authorizationUrl = auth.getAuthorizationUrl({ state });
    // Store `state` in the user's session, then redirect them to `authorizationUrl`
```

#### Rückruf verarbeiten

Wenn Benutzende von Adobe IMS wieder an Ihre `redirectUri` zurückgeleitet werden, extrahieren Sie die Parameter `code` und `state`.Überprüfen Sie, ob der Status mit dem gespeicherten übereinstimmt, und tauschen Sie dann den Code gegen Token aus:

```typescript
    // In your callback handler (e.g. an Express route):
    await auth.exchangeCode(req.query.code as string);
```

Hiermit wird der Autorisierungscode gegen einen Zugriffstoken und einen Aktualisierungstoken ausgetauscht, und beide werden intern gespeichert.

#### Client verwenden

```typescript
    import { FrameioClient } from "frameio";

    const client = new FrameioClient({ token: () => auth.getToken() });
```

Das ist alles.Von diesem Punkt an wird der Token-Lebenszyklus automatisch von `getToken()` verwaltet.Wenn der Zugriffstoken kurz vor dem Ablauf steht, wird vom SDK mit dem Aktualisierungstoken ein neuer angefordert.Keine Benutzendeninteraktion erforderlich.

### Vollständiges Express-Beispiel

```typescript
import crypto from "crypto";
import express from "express";
import session from "express-session";
import { FrameioClient, WebAppAuth } from "frameio";

const auth = new WebAppAuth({
    clientId: "YOUR_CLIENT_ID",
    clientSecret: "YOUR_CLIENT_SECRET",
    redirectUri: "http://localhost:3000/callback",
});

const app = express();
app.use(session({ secret: crypto.randomBytes(32).toString("hex"), resave: false, saveUninitialized: false }));

app.get("/login", (req, res) => {
    const state = crypto.randomBytes(32).toString("hex");
    (req.session as any).oauthState = state;
    res.redirect(auth.getAuthorizationUrl({ state }));
});

app.get("/callback", async (req, res) => {
    if (req.query.state !== (req.session as any).oauthState) {
        return res.status(403).send("Invalid state parameter");
    }

    await auth.exchangeCode(req.query.code as string);

    const client = new FrameioClient({ token: () => auth.getToken() });
    const accounts = await client.accounts.index();
    res.json(accounts);
});

app.listen(3000);
```

---

## Single Page App / PKCE (Autorisierungscode und PKCE)

Dies ist für browserbasierte Anwendungen, Desktop-Anwendungen oder CLI-Tools vorgesehen, in denen ein Clientschlüssel nicht sicher gespeichert werden kann.In dem Fluss wird [PKCE (RFC 7636)](https://datatracker.ietf.org/doc/html/rfc7636) eingesetzt, um den Austausch des Autorisierungscodes zu schützen.

#### Autorisierungs-URL generieren

```typescript
    import { SPAAuth } from "frameio";

    const auth = new SPAAuth({
        clientId: "YOUR_CLIENT_ID",
        redirectUri: "https://yourapp.com/callback",
    });

    const state = crypto.randomUUID();
    const result = await auth.getAuthorizationUrl({ state });
    // result.url            -> redirect the user here
    // result.codeVerifier   -> store this securely until the callback
```

Mit `getAuthorizationUrl` wird ein `AuthorizationUrlResult` zurückgegeben, das die vollständige URL (mit der eingebetteten PKCE `code_challenge`) und den `codeVerifier` enthält, den Sie im nächsten Schritt benötigen.

#### Codes mittels Codeprüfer austauschen

Wenn Benutzende zurückgeleitet werden:

```typescript
    await auth.exchangeCode({
        code: "CODE_FROM_CALLBACK",
        codeVerifier: result.codeVerifier,
    });
```

#### Client verwenden

```typescript
    import { FrameioClient } from "frameio";

    const client = new FrameioClient({ token: () => auth.getToken() });
```

Das ist alles.Aktualisierung funktioniert genauso wie die Web-Anwendung – der Aktualisierungstoken wird automatisch vom SDK verwendet.Der Unterschied besteht darin, dass während der Aktualisierung kein Clientschlüssel gesendet wird, da der SPA-Fluss für öffentliche Clients konzipiert ist.

> **Warning**
>
> Der `codeVerifier` muss clientseitig sicher zwischen der Autorisierungsanfrage und dem Code-Austausch gespeichert werden.Nutzen Sie dazu `sessionStorage` oder eine entsprechende Funktion in Browser-Anwendungen.

---

## Native App (Autorisierungscode und PKCE)

Verwenden Sie dies für Desktop- und mobile Anwendungen.Wenn Sie in der [Adobe Developer Console](https://developer.adobe.com/console) Anmeldedaten für eine Native App erstellen, wird Ihnen von Adobe eine Umleitungs-URI in der Form `adobe+<hash>://callback</hash>` zugewiesen. Sie registrieren Ihre Anwendung, um dieses selbstdefinierte URI-Schema auf BS-Ebene zu verarbeiten.Loopback-Umleitungen (`http://127.0.0.1:<port>/callback</port>`) werden bei der lokalen Entwicklung ebenfalls unterstützt.Der Fluss ist mit SPA identisch, dabei wird PKCE ohne Clientschlüssel verwendet.

```typescript
import { NativeAppAuth } from "frameio";

const auth = new NativeAppAuth({
    clientId: "YOUR_CLIENT_ID",
    redirectUri: "adobe+abc123def456://callback", // from your Adobe Developer Console Native App credential
    // Also supports loopback: "http://127.0.0.1:8080/callback"
});

const { url, codeVerifier } = await auth.getAuthorizationUrl({
    state: crypto.randomUUID(),
});

// Open system browser to `url`
// Listen for redirect on your custom URI scheme or loopback server

await auth.exchangeCode({ code: "CODE_FROM_REDIRECT", codeVerifier });
const client = new FrameioClient({ token: () => auth.getToken() });
```

### Regeln für Umleitungs-URIs

Die Regeln für Umleitungs-URI werden an zwei Punkten von Adobe durchgesetzt: wenn Sie die Anmeldedaten in der [Adobe Developer Console](https://developer.adobe.com/console) registrieren, und wenn der Parameter `redirect_uri` den Endpunkt `/authorize/v2` erreicht.Der Wert, den Sie in diesem SDK an `redirectUri` weitergeben, muss einem der „Umleitungs-URI-Muster“ entsprechen, die Sie für die Anmeldedaten registriert haben. Andernfalls wird zu dem Standard-Umleitungs-URI der Anmeldedaten umgeleitet.

* Für die Anmeldedaten für **Web-Anwendungen** und **SPA** ist HTTPS erforderlich.
* Bei Anmeldedaten für **Native App** wird eine nicht-HTTPS-Umleitung verwendet, in der Regel der `adobe+<hash>://callback</hash>`-URI, der in der Developer Console für die Anmeldedaten angezeigt wird.

Die genauen Muster, die für Ihre Anmeldedaten akzeptiert werden, finden Sie in der [Adobe Developer Console](https://developer.adobe.com/console).

> **Note**
>
> Das Python-SDK enthält keine Native App-Anmeldedatenklasse, da Python keine Standardmethode zur Registrierung selbstdefinierter
>
> URI-Schema-Handler hat.Vom TypeScript-SDK werden alle vier Arten von Anmeldedaten unterstützt, einschließlich Native App.

---

## Manuelle Aktualisierung der Token

Bei Web-Anwendungs-, SPA- und Native App-Flüssen werden Token durch das SDK automatisch über `getToken()` aktualisiert.Falls Sie explizite Steuerung benötigen, können Sie `refresh()` direkt aufrufen:

```typescript
await auth.refresh(); // fetches a new access token using the refresh token
```

Das ist nützlich, wenn Sie vor einem wichtigen Vorgang eine Aktualisierung erzwingen möchten, anstatt sich auf den automatischen Aktualisierungspuffer zu verlassen.

`refresh()` ist in `WebAppAuth`, `SPAAuth` und `NativeAppAuth` verfügbar.Damit wird ein `ConfigurationError` ausgelöst, wenn kein Aktualisierungstoken verfügbar ist (d. h., Sie müssen zuerst `exchangeCode()` aufrufen).Bei `ServerToServerAuth` gibt es keine `refresh()`-Methode. Hier wird `authenticate()` verwendet, um stattdessen über Client-Anmeldedaten ein neues Token abzurufen.

---

## Token-Persistenz

`exportTokens()` und `importTokens()` werden von allen Auth-Klassen unterstützt, um den Tokenstatus auch nach Neustarts aufrechtzuerhalten.Für Web-Anwendungs-, SPA- und Native App-Flows ist das besonders wichtig, da Zugriffs- und Aktualisierungstoken standardmäßig im Arbeitsspeicher gespeichert werden. Wenn Ihre Anwendung neu startet, müssten Benutzende sich erneut authentifizieren, es sei denn, Sie speichern sie dauerhaft.Bei Server-zu-Server ist die Persistenz optional (es kann immer ein neuer Token mit den Anmeldedaten erstellt werden), doch durch das Importieren eines zwischengespeicherten Tokens wird ein zusätzlicher Umlauf beim Start vermieden.

### Exportieren und Importieren

```typescript
// After exchangeCode(), save the token state
const tokenData = auth.exportTokens();
// tokenData is: { access_token: "...", refresh_token: "...", expires_at: 1234567890.0 }
// Save it to your database, file, or secret store

// On next startup, restore it
auth.importTokens(tokenData);
const client = new FrameioClient({ token: () => auth.getToken() });
// The SDK will automatically refresh if the token is near expiry
```

> **Warning**
>
> Speichern Sie exportierte Token sicher.Sie enthalten Zugriffs- und Aktualisierungstoken, die API-Zugriff gewähren.Schreiben Sie keine Token
>
> in der Produktion in Klartext-Dateien.

### Automatische Persistenz mit `onTokenRefreshed`

Damit Token bei jeder Aktualisierung automatisch dauerhaft gespeichert werden, verwenden Sie den Rückruf `onTokenRefreshed`:

```typescript
import fs from "fs/promises";

const TOKEN_FILE = "tokens.json";

const auth = new WebAppAuth({
    clientId: "...",
    clientSecret: "...",
    redirectUri: "...",
    onTokenRefreshed: (tokens) => {
        fs.writeFile(TOKEN_FILE, JSON.stringify(tokens));
    },
});

// On startup, restore if available
try {
    const saved = JSON.parse(await fs.readFile(TOKEN_FILE, "utf-8"));
    auth.importTokens(saved);
} catch {
    // No saved tokens — user will need to authenticate
}
```

Der Rückruf erhält die gleiche Form wie `exportTokens()` und wird nach jeder erfolgreichen Tokenaktualisierung ausgelöst.

---

## Widerrufen von Token

So melden Sie Benutzende ab und machen deren Token mit Adobe IMS ungültig:

```typescript
await auth.revoke();
```

Damit werden parallel zwei bestmögliche Widerrufsanfragen an Adobe IMS gesendet, eine für den Zugriffstoken und eine für den Aktualisierungstoken. Anschließend wird der Status aller lokalen Token gelöscht. Bei vertraulichen Clients (`WebAppAuth`) wird HTTP Basic Auth für Widerrufsanfragen verwendet; bei öffentlichen Clients (`SPAAuth`, `NativeAppAuth`) wird die `client_id` als Abfrageparameter gesendet.Widerrufsfehler werden protokolliert, aber nicht ausgelöst.Nach dem Widerruf müssen Benutzende sich erneut authentifizieren.

---

## Fehlerbehandlung

Alle Authentifizierungsfehler übernehmen von `FrameioAuthError`, sodass Sie sie allgemein abfangen oder spezifische Fälle behandeln können:

```typescript
import {
    FrameioAuthError,
    AuthenticationError,
    TokenExpiredError,
    ConfigurationError,
    NetworkError,
    RateLimitError,
} from "frameio";

try {
    await auth.exchangeCode("...");
} catch (error) {
    if (error instanceof TokenExpiredError) {
        // The refresh token has expired; redirect the user to sign in again
    } else if (error instanceof AuthenticationError) {
        // Token exchange failed
        console.error(`Error: ${error.errorCode} - ${error.errorDescription}`);
    } else if (error instanceof NetworkError) {
        // Timeout or connection failure (after retries)
    } else if (error instanceof RateLimitError) {
        // 429 from Adobe IMS; retry after error.retryAfter seconds
    } else if (error instanceof FrameioAuthError) {
        // Catch-all for any other auth error
    }
}
```

### Fehlerreferenz

| Ausnahme              | Wann sie ausgelöst wird                                                                                                   |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `ConfigurationError`  | Fehlende oder ungültige Konfiguration (z. B. leere `clientId`, nicht-HTTPS-Weiterleitungs- URI, nicht-HTTPS-`imsBaseUrl`) |
| `AuthenticationError` | Tokenaustausch oder -aktualisierung von Adobe IMS abgelehnt (hat `.errorCode` und `.errorDescription`)                    |
| `TokenExpiredError`   | Aktualisierungstoken selbst ist abgelaufen; Benutzende müssen sich erneut authentifizieren                                |
| `NetworkError`        | HTTP-Timeout oder Verbindungsfehler nach allen Wiederholungsversuchen                                                     |
| `RateLimitError`      | 429 von Adobe IMS zurückgegeben; sehen Sie unter `.retryAfter` für Anleitung bzgl. Backoff nach                           |
| `PKCEError`           | Verfügbar für die Nutzung durch Verbrauchende in PKCE-Flows; wird nicht intern vom SDK ausgelöst                          |

### Umgang mit abgelaufenen Aktualisierungstoken in der Produktion

> **Warning**
>
> Bei Web-Anwendungs-, SPA- und der Native App-Flows läuft der Aktualisierungstoken irgendwann ab. Wenn das geschieht, wird von `getToken()` ein `TokenExpiredError` ausgelöst.Diesen sollten Sie abfangen und Benutzende erneut durch den Autorisierungsfluss leiten.

```typescript
import { TokenExpiredError } from "frameio";

try {
    const client = new FrameioClient({ token: () => auth.getToken() });
    const assets = await client.files.list({ projectId: "..." });
} catch (error) {
    if (error instanceof TokenExpiredError) {
        // Clear persisted tokens and redirect user to login
        await auth.revoke();
        return res.redirect("/login");
    }
}
```

---

## Konfigurationsreferenz

Diese Parameter haben sinnvolle Standardwerte und müssen selten eingestellt werden.Falls Sie das Verhalten anpassen müssen – etwa auf ein Staging-IMS weisen, einen selbstdefinierten `fetch` einschleusen, Timeouts anpassen oder eine Protokolleinrichtung verschalten – übergeben Sie beim Erstellen der Authentifizierungsklasse beliebige davon als optionale Parameter:

| Parameter          | Standard                         | Beschreibung                                                                                                                                                                                                                                                 |
| ------------------ | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `scopes`           | Flussspezifische Standardwerte   | Durch Leerzeichen getrennte OAuth-Gültigkeitsbereiche.Bei S2S wird standardmäßig `openid AdobeID frame.s2s.all` verwendet; bei an Benutzenden orientierten Flüssen wird standardmäßig `openid email profile offline_access additional_info.roles` verwendet. |
| `imsBaseUrl`       | `https://ims-na1.adobelogin.com` | Basis-URL von Adobe IMS.Überschreibung für Staging- oder Nichtproduktionsumgebungen.Muss HTTPS verwenden.                                                                                                                                                    |
| `fetch`            | `globalThis.fetch`               | Selbstdefinierte `fetch`-Implementierung für Proxy, mTLS oder selbstdefinierte HTTP-Verarbeitung.                                                                                                                                                            |
| `timeout`          | `30000`                          | Timeout der HTTP-Anfrage in Millisekunden für Token-Endpunkt-Aufrufe.                                                                                                                                                                                        |
| `maxRetries`       | `2`                              | Maximale Anzahl von Wiederholungen für vorübergehende Fehler (5xx, Timeouts).Wiederholungen bei Ratenbegrenzungen (429) werden separat verfolgt.                                                                                                             |
| `refreshBuffer`    | `60`                             | Sekunden vor Ablauf des Tokens, um proaktive Aktualisierung auszulösen.                                                                                                                                                                                      |
| `onTokenRefreshed` | `undefined`                      | Rückruf wird nach jeder erfolgreichen Tokenaktualisierung ausgelöst.Erhält ein Objekt mit `access_token`, `refresh_token` und `expires_at`.                                                                                                                  |
| `logger`           | No-op (still)                    | Instanz der Protokolleinrichtung mit den Methoden `debug`, `info`, `warn`, `error` (z. B. `console`, `pino`, `winston`).                                                                                                                                     |

### Staging-Umgebungen

Weisen Sie auf eine Staging-Instanz von Adobe IMS, indem Sie `imsBaseUrl` überschreiben.Vom SDK wird auch `DEFAULT_IMS_BASE_URL` (`https://ims-na1.adobelogin.com`) exportiert, falls Sie den Produktionswert programmgesteuert referenzieren müssen.

```typescript
const auth = new ServerToServerAuth({
    clientId: "...",
    clientSecret: "...",
    imsBaseUrl: "https://ims-na1-stg1.adobelogin.com",
});
```

### Selbstdefinierter Abruf

Für Proxy-Unterstützung oder selbstdefinierte TLS-Konfiguration:

```typescript
import { ProxyAgent } from "undici";

const proxyAgent = new ProxyAgent("http://corporate-proxy:8080");

const auth = new ServerToServerAuth({
    clientId: "...",
    clientSecret: "...",
    fetch: (url, init) => fetch(url, { ...init, dispatcher: proxyAgent }),
});
```

---

## Sicherheit bei Nebenläufigkeit

Das TypeScript SDK kann bedenkenlos nebenläufig verwendet werden.Wenn mehrere `getToken()`-Aufrufe gleichzeitig stattfinden und eine Aktualisierung erforderlich ist, wird nur eine Aktualisierungsanfrage ausgelöst.Die anderen warten auf dasselbe Versprechen und erhalten dasselbe Ergebnis.Es ist keine externe Sperrung erforderlich.Bei dieser Deduplizierung wird die Ereignisschleife mit einzelnem Thread von JavaScript und ein geteiltes `Promise` verwendet. Falls bereits eine Aktualisierung läuft, schließen gleichzeitige Aufrufer sich dieser an, anstatt eine zweite Anfrage zu starten.Wird während einer Aktualisierung `revoke()` aufgerufen, wird die Aktualisierung mit einem `AuthenticationError` abgelehnt und die Token bleiben gelöscht – der Widerruf hat stets Vorrang.