---
title: "Mit OAuth verbinden"
description: "Autorisieren Sie MCP-Clients und die ThunderPhone CLI, ohne einen API-Schlüssel weiterzugeben."
---

OAuth ermöglicht einer App, sich mit einer ThunderPhone-Organisation mit den von Ihnen genehmigten Berechtigungen zu verbinden. Verzeichnis-Clients sollten standardmäßig OAuth verwenden. Organisations-API-Schlüssel bleiben für Clients verfügbar, die ein manuell konfiguriertes Bearer-Token benötigen.

## Eine Verbindung genehmigen

Starten Sie die Verbindung in Ihrem MCP-Client. Melden Sie sich bei ThunderPhone an, prüfen Sie den App-Namen und die angeforderten Berechtigungen, wählen Sie eine Organisation aus und klicken Sie auf **Genehmigen**. Wählen Sie **Ablehnen**, wenn Sie die Verbindung nicht gestartet haben oder der App nicht vertrauen. App-Namen werden von ihren Entwicklern bereitgestellt und sind kein Verifizierungsnachweis.

Leseberechtigungen legen die benannten Daten offen, einschließlich Aufzeichnungen und Transkripten, wenn `calls:read` angefordert wird. Schreibberechtigungen können Ressourcen ändern oder löschen; Anrufe, Kampagnen, Telefonnummernkäufe und Bereitstellungen können Kosten verursachen oder die Produktion beeinträchtigen. Ihre Organisationsrolle gilt weiterhin.

Öffnen Sie für eine CLI-Verbindung den in Ihrem Terminal angezeigten Verifizierungslink, vergleichen Sie den acht Zeichen langen Code, wählen Sie Ihre Organisation aus und genehmigen Sie die Verbindung. Das bloße Öffnen des Links gewährt keinen Zugriff. Codes laufen nach 15 Minuten ab.

## Verbindung zu einer App trennen

Öffnen Sie im Dashboard **Organisation → API-Schlüssel → Autorisierte Apps** und wählen Sie **Widerrufen**. Dadurch wird Ihre ausgewählte Autorisierung für die aktuelle Organisation widerrufen, einschließlich ihrer Zugriffs- und Aktualisierungstoken. Stellen Sie die Verbindung über die App erneut her, wenn Sie sie wieder autorisieren möchten.

## Ermittlung für MCP-Clients

Verwenden Sie die Server-URL `https://api.thunderphone.com/v1/mcp`. Eine Anfrage ohne gültige Authentifizierung erhält `401` mit:

```http
WWW-Authenticate: Bearer resource_metadata="https://api.thunderphone.com/.well-known/oauth-protected-resource"
```

Rufen Sie dieses Dokument ab und rufen Sie dann die Metadaten des Autorisierungsservers unter `https://api.thunderphone.com/.well-known/oauth-authorization-server` ab. Ressourcenmetadaten sind auch unter `/.well-known/oauth-protected-resource/v1/mcp` verfügbar. Verwenden Sie die zurückgegebenen Endpunkte, anstatt sie zu konstruieren. Die Ressourcenkennung lautet `https://api.thunderphone.com/v1/mcp`.

Der Server unterstützt den Autorisierungscode-Flow mit **S256 PKCE**, rotierende Refresh-Tokens, öffentliche dynamische Client-Registrierung, Widerruf und den Device Authorization Grant. Es gibt keine Client-Secrets oder impliziten Grants. Die OpenID-Ermittlung ist auch unter `/.well-known/openid-configuration` verfügbar; sie enthält dieselben Autorisierungsserver-Felder sowie `subject_types_supported: ["public"]` und den Userinfo-Endpunkt. ID-Tokens und Client-ID-Metadatendokumente (CIMD) werden nicht unterstützt.

### Einen öffentlichen Client registrieren

Senden Sie JSON an `POST /v1/oauth/register`:

```json
{
  "client_name": "My MCP client",
  "redirect_uris": ["http://127.0.0.1:8765/callback"],
  "token_endpoint_auth_method": "none",
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"]
}
```

Speichern Sie die zurückgegebene `client_id`. Weiterleitungen müssen HTTPS verwenden oder HTTP auf `127.0.0.1` oder `localhost`. Registrieren Sie die exakte Callback-URI einschließlich Port und Pfad. Fragmente und eingebettete Anmeldedaten werden abgelehnt. Optionale `client_uri` und `logo_uri` müssen HTTPS verwenden; ThunderPhone ruft sie bei der Registrierung nicht ab. Die Registrierung ist rate-limitiert. Registrierte Clients laufen nicht ab und bleiben registriert, wenn eine Verbindung widerrufen wird. HTTPS-Callbacks umfassen `https://chatgpt.com/connector/oauth/<id>` und `https://chatgpt.com/connector_platform_oauth_redirect`. Jede Verbindung kann einen eigenen Client registrieren.

### Autorisierungscode

Öffnen Sie den ermittelten Autorisierungsendpunkt mit `client_id`, der exakt registrierten `redirect_uri`, `response_type=code`, einem zufälligen `state`, `scope`, `code_challenge`, `code_challenge_method=S256` und `resource=https://api.thunderphone.com/v1/mcp`. Berechnen Sie die Challenge als ungepolsterten base64url-SHA-256-Digest eines neuen PKCE-Verifiers mit hoher Entropie. Prüfen Sie den zurückgegebenen `state` und `iss`, bevor Sie den Code austauschen. Jede Autorisierungsantwort, einschließlich Ablehnungen und Protokollfehlern, identifiziert den Issuer mit `iss`, das exakt mit dem ermittelten `issuer` übereinstimmt. Fehler für einen ungültigen Client oder Callback werden lokal zurückgegeben, ohne zu diesem Callback weiterzuleiten.

Tauschen Sie am Endpunkt `POST /v1/oauth/token` unter Verwendung von Formularcodierung aus (JSON wird ebenfalls akzeptiert):

```text
grant_type=authorization_code
client_id=<your client id>
code=<single-use authorization code>
redirect_uri=<exact registered redirect URI>
code_verifier=<original PKCE verifier>
resource=https://api.thunderphone.com/v1/mcp
```

Der optionale Parameter `resource` wird sowohl bei Autorisierungs- als auch bei Token-Anfragen akzeptiert, einschließlich Refresh- und Device-Austauschvorgängen. Wenn er ausgelassen wird, ist standardmäßig die ermittelte MCP-Ressource festgelegt. Wenn er vorhanden ist, muss er exakt mit dieser Ressource übereinstimmen; andere Werte geben `invalid_target` zurück. Access-Tokens enthalten diese Audience, und MCP lehnt Tokens mit fehlender oder abweichender Audience mit `401` und einer Discovery-Challenge ab.

Autorisierungsanfragen und Codes laufen nach 10 Minuten ab. Jede Token-Antwort enthält `access_token`, `token_type` (`Bearer`), `expires_in` (standardmäßig 3600 Sekunden), `refresh_token`, `scope`, `organization_id` und `organization_name`. Senden Sie Access-Tokens ausschließlich über den Header `Authorization: Bearer`. Speichern Sie Tokens niemals in URLs, Logs, Versionsverwaltung oder Chats.

### Aktualisieren und widerrufen

Aktualisieren Sie am Token-Endpunkt mit `grant_type=refresh_token`, `client_id`, `refresh_token` und `resource`. Speichern Sie das neue Refresh-Token atomar und verwenden Sie das alte nicht mehr. Refresh-Tokens laufen nach 30 Tagen ohne erfolgreiche Aktualisierung ab. Ein optionales `scope` kann die gewährten Berechtigungen einschränken. `offline_access` ist immer enthalten und Refresh-Tokens werden immer ausgestellt. Eine anfängliche Anfrage ohne `scope` gewährt nur `offline_access`; Clients sollten daher die benötigten Berechtigungen anfordern.

Die Wiederverwendung von Codes und rotierten Refresh-Tokens widerruft die gesamte Autorisierung. Serialisieren Sie Aktualisierungen innerhalb eines Clients; das erneute Abspielen einer erfolgreich ausgetauschten Anmeldeinformation ist keine sichere Wiederholungsstrategie.

Um die Verbindung zu trennen, senden Sie `token` und `client_id` an `POST /v1/oauth/revoke`. Der Widerruf eines der beiden Tokens widerruft dessen Autorisierung, einschließlich aller daraus ausgestellten Tokens. Ein unbekanntes Token gibt Erfolg zurück, ohne offenzulegen, ob es existiert. Dashboard-Sitzungen können ihre eigenen Autorisierungen über `GET /v1/oauth/grants` auflisten und eine über `DELETE /v1/oauth/grants/<id>` widerrufen, wobei `X-ThunderPhone-Org` die Organisation auswählt.

### Geräteautorisierung

Die Geräteautorisierung ist auf vorregistrierte Clients beschränkt; dynamisch registrierte Clients erhalten `unauthorized_client`. Der vorregistrierte öffentliche Client `thunderphone-cli` unterstützt Geräteautorisierung und Aktualisierung. Senden Sie `client_id=thunderphone-cli` und `scope` an `POST /v1/oauth/device/code`. Zeigen Sie dem Benutzer `user_code` und `verification_uri` an oder öffnen Sie `verification_uri_complete`.

Fragen Sie den Token-Endpunkt mit `grant_type=urn:ietf:params:oauth:grant-type:device_code`, `client_id` und `device_code` ab und warten Sie mindestens das zurückgegebene `interval` (5 Sekunden). Fahren Sie bei `authorization_pending` fort. Verwenden Sie bei `slow_down` für jede nachfolgende Anfrage das in der Antwort zurückgegebene neue `interval` (um 5 Sekunden erhöht). Beenden Sie den Vorgang bei `access_denied`, `expired_token` oder jedem anderen Fehler. Genehmigen Sie einen Gerätecode niemals automatisch.

Der vorregistrierte Client `thunderphone-mcp` akzeptiert `http://127.0.0.1/callback` und `http://localhost/callback` auf jedem Port. Schema, Host, Pfad und Query müssen übereinstimmen; der Token-Austausch muss die exakte Redirect-URI einschließlich Port aus der Autorisierung verwenden. Dynamisch registrierte Clients erfordern eine exakte Übereinstimmung der Redirect-URI einschließlich Port. Registrieren Sie dynamisch einen anderen Callback, wenn Sie einen anderen Pfad benötigen.

### Kontoidentität und Prüfungen der Workspace-Domain

Fordern Sie zusätzlich zu den von Ihrem Client benötigten Operations-Scopes sowohl `openid email` an. Rufen Sie den ermittelten `userinfo_endpoint` (`GET /v1/oauth/userinfo`) mit dem Access-Token im Bearer-Header auf. Eine erfolgreiche Antwort enthält:

```json
{
  "sub": "123",
  "email": "person@example.com",
  "email_verified": true,
  "name": "Example User",
  "org_id": 456
}
```

`sub` ist die stabile Benutzerkennung; `org_id` ist die während der Einwilligung ausgewählte Organisation. Der Endpunkt erfordert beide Identitäts-Scopes und gibt `403` zurück, wenn einer fehlt. Er gibt `403` mit `error=access_denied` zurück, wenn das Konto kein verifiziertes E-Mail-Profil hat, anstatt zu behaupten, dass eine nicht verifizierte E-Mail vertrauenswürdig ist. Ungültige, abgelaufene, widerrufene Tokens oder Tokens mit falscher Audience geben `401` zurück. Tokens menschlicher Sitzungen und Organisations-API-Schlüssel können Userinfo nicht aufrufen. Es wird kein ID-Token ausgestellt.

## Verfügbare Berechtigungen

| Familie | Bereiche |
| --- | --- |
| Agenten und Agentenimporte | `agents:read`, `agents:write` |
| Anrufe | `calls:read`, `calls:write` |
| Telefonnummern, blockierte Anrufer und VoIP | `numbers:read`, `numbers:write` |
| Wissen | `knowledge:read`, `knowledge:write` |
| Kampagnen | `campaigns:read`, `campaigns:write` |
| Integrationen, Webhook-Endpunkte, MCP-Server | `integrations:read`, `integrations:write` |
| Stimmen | `voices:read` |
| Testszenarien, Testläufe, Validierung | `testing:read`, `testing:write` |
| Abrechnung | `billing:read` |
| Kontoidentität und verifizierte E-Mail-Adresse | `openid`, `email` (beide für userinfo erforderlich) |
| Persistente Verbindung | `offline_access` (immer enthalten) |

GET, HEAD und OPTIONS verwenden Leseberechtigungen; andere Methoden verwenden Schreibberechtigungen. Änderungen an Stimmen und der Abrechnung sind über OAuth nicht verfügbar; `POST /v1/voices/preview` verwendet `voices:read`, da eine Stimme in der Vorschau angezeigt wird, ohne ihre Konfiguration zu ändern. MCP-Tools erzwingen die Berechtigung der zugrunde liegenden REST-Operation. Organisationsübergreifende Übertragungen werden abgelehnt, selbst wenn der autorisierende Benutzer beiden Organisationen angehört. Andere API-Kategorien, einschließlich der Verwaltung von API-Schlüsseln und Einstellungen für menschliche Konten, sind über OAuth nicht verfügbar. Eine fehlende Berechtigung für eine REST-Operation gibt `403` mit `WWW-Authenticate: Bearer error="insufficient_scope", scope="..."` zurück. Ungültige oder abgelaufene Zugriffstoken geben `401` zurück.


### MCP-Tool-Authentifizierungssignale

Jedes Tool in `tools/list` enthält `securitySchemes: [{"type": "oauth2", "scopes": ["agents:read"]}]` mit der Berechtigung der REST-Operation dieses Tools. Öffentliche Dokumentationstools verwenden eine leere Berechtigungsliste und erfordern weiterhin eine authentifizierte Verbindung.

Ein gültiges Token, dem die Berechtigung eines Tools fehlt, erhält HTTP `200` mit einem JSON-RPC-`result`, das `isError: true`, erläuternden Text in `content` und `_meta["mcp/www_authenticate"]` enthält. Letzteres ist ein Array mit einer Bearer-Challenge mit `resource_metadata`, `error="insufficient_scope"`, `error_description` und der erforderlichen `scope`. Das Tool wird nicht ausgeführt. Verwenden Sie diese Challenge, um eine erweiterte Einwilligung anzufordern. Fehlende oder ungültige Authentifizierung gibt weiterhin HTTP `401` mit `WWW-Authenticate` zurück; REST-Berechtigungsfehler geben weiterhin HTTP `403` zurück.

## Speicherung von Anmeldedaten

Die API führt `python manage.py oauth_cleanup` stündlich in Staging und Produktion aus. Dabei werden abgelaufene Autorisierungsanfragen und Gerätecodes entfernt. Abgelaufene Zugriffstoken, Autorisierungscodes und Refresh-Token-Hashes werden erst bereinigt, nachdem ihre Berechtigung widerrufen wurde oder die gesamte Tokenfamilie ungültig ist. Verwendete Hashes werden aufbewahrt, solange die Familie ein verwendbares Refresh-Token, einen Autorisierungscode, einen genehmigten Gerätecode oder ein Zugriffstoken besitzt, damit die Bereinigung die Erkennung von Wiederholungsangriffen nicht deaktivieren kann.
