
# OIDC-Konfiguration einer Verbindung anlegen oder ersetzen

`PUT /v1/connections/{connection_id}/oidc` · Berechtigung `connections:write`

Legt die Konfiguration der vertrauenden Partei einer Unternehmens-OIDC-Verbindung an oder ersetzt sie vollständig.

- **Erstmaliger Schreibvorgang:** Senden Sie keinen `If-Match`-Header und geben Sie `sp_host` an (ein aktiver Host dieser Umgebung). Der Callback `https://<sp_host>/sso/<connection_id>/callback` ist ab dann festgelegt. Die Antwort ist `201 Created`. Wird `If-Match` gesendet, solange noch keine Konfiguration existiert, schlägt die Anfrage mit `412` fehl.
- **Aktualisierung:** `If-Match` ist erforderlich. Ohne diesen Header schlägt die Anfrage mit `428` fehl, und es wird nichts geschrieben. Eine Anfrage ohne den Header kann daher nie eine bestehende Konfiguration überschreiben. Wurde die Konfiguration seit dem Lesen geändert (oder stimmt der Wert nicht überein), schlägt die Anfrage mit `412` fehl. `*` entspricht der aktuellen Konfiguration. `sp_host` muss leer sein oder dem gespeicherten Host entsprechen.

Das Client-Geheimnis ist nur schreibbar: Es wird nie zurückgegeben, nie protokolliert und nie im Audit-Log festgehalten. Wenn Sie ohne `client_secret` aktualisieren, bleibt das gespeicherte Geheimnis erhalten. `private_key_jwt` entfernt es (der Signierschlüssel der Umgebung signiert die Client-Assertion). Ein geänderter `issuer` löscht das gespeicherte Discovery-Dokument. Ein geänderter `issuer` oder `client_id` macht den letzten bestandenen Verbindungstest ungültig. Das Senden derselben Konfiguration schreibt nichts. Schreibvorgänge werden als `connection.protocol_config_created` oder `connection.oidc_config_updated` protokolliert (nur geänderte Felder; das Geheimnis erscheint nur als `client_secret_set`).

Bei einer **aktiven** Verbindung wird eine Aktualisierung, die `issuer` oder `client_id` ändert, nicht sofort angewendet. Die gesamte Anfrage (einschließlich eines neuen Geheimnisses) wird zu einer [Entwurfsrevision](../connections/revisions.md): Die Antwort ist `200 OK` mit der unveränderten live Konfiguration, dem unveränderten `ETag` und einem Feld `revision`. Testen Sie den Entwurf mit [Eine Verbindung testen](../connections/test.md) und `revision_id` und [veröffentlichen Sie ihn anschließend](../connections/publish-revision.md). Andere Aktualisierungen werden direkt angewendet.

## Anfrage

| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
| `connection_id` | path | ja | ID der Unternehmens-OIDC-Verbindung (`conn_…`). |
| `If-Match` | header | bei Aktualisierung | Das `ETag` aus dem letzten Lese- oder Schreibvorgang. Fehlt es bei einer Aktualisierung: `428`; veraltet: `412`. Bei der erstmaligen Anlage nicht senden. |
| `sp_host` | string | bei erstmaliger Anlage | Aktiver Host dieser Umgebung (Kleinbuchstaben). Bei Aktualisierung leer oder der gespeicherte Host. |
| `issuer` | string | ja | Absolute `https`-URL ohne Query oder Fragment, höchstens 512 Byte. |
| `client_id` | string | ja | 1–255 Byte, keine Steuerzeichen. |
| `client_auth_method` | string | ja | `private_key_jwt` (empfohlen; kein Geheimnis wird gespeichert), `client_secret_basic` oder `client_secret_post`. |
| `client_secret` | string | nein | Nur schreibbar, höchstens 1024 Byte. Wird bei Aktualisierung ohne Angabe beibehalten. Bei `private_key_jwt` nicht zulässig. |
| `client_secret_expires_at` | string \| null | nein | Zeitpunkt, zu dem der Identitätsanbieter das Geheimnis ablaufen lässt (RFC 3339). Nur zusammen mit `client_secret`. |
| `provider_profile` | string | nein | `entra`, `okta`, `google`, `keycloak`, `ping`, `onelogin`, `jumpcloud` oder `generic` (Standard). |
| `entra_tenant_id` | string | bei `entra` | Die Mandanten-ID von Microsoft Entra (UUID); nur für das Profil `entra`. |

## Antwort

`201 Created` beim erstmaligen Schreibvorgang, `200 OK` bei einer Aktualisierung, mit der Konfiguration (siehe [OIDC-Konfiguration abrufen](get.md)) und dem neuen `ETag`. Das Client-Geheimnis ist nicht in der Antwort enthalten. Wurde die Aktualisierung zu einer Entwurfsrevision, enthält der Body zusätzlich `revision` (der Entwurf); Konfiguration und `ETag` sind dann die live Werte.

## Fehler

| HTTP | code | Wann |
|---|---|---|
| 404 | `not_found` | Die Verbindung existiert in dieser Umgebung nicht oder ist keine Unternehmensverbindung. |
| 409 | `conflict` | Die Verbindung ist keine OIDC-Verbindung, `sp_host` weicht vom gespeicherten Host ab, oder eine Methode mit Geheimnis hat kein gespeichertes oder angegebenes Geheimnis. |
| 412 | `precondition_failed` | `If-Match` stimmt nicht mit der aktuellen Version überein, die Konfiguration wurde parallel geändert, oder `If-Match` wurde vor dem ersten Schreibvorgang gesendet. |
| 422 | `validation_failed` | Ein Feld verletzt die oben genannten Regeln; `errors[]` verweist auf das Feld (`/issuer`, `/client_id`, `/client_auth_method`, `/client_secret`, `/client_secret_expires_at`, `/provider_profile`, `/entra_tenant_id`, `/sp_host`). |
| 428 | `precondition_required` | Die Konfiguration existiert, und der Header `If-Match` fehlt. |
| 400 | `unknown_field` | Der Body enthält ein unbekanntes Feld. |
| 401 | `unauthenticated` | Die Anmeldedaten fehlen, sind ungültig oder wurden widerrufen. |
| 403 | `insufficient_permissions` | Den Anmeldedaten fehlt die erforderliche Berechtigung. |
| 429 | `rate_limited` | Das Ratenlimit wurde überschritten; wiederholen Sie die Anfrage nach dem Zeitraum aus `Retry-After`. |
| 503 | `service_unavailable` | Eine Abhängigkeit ist vorübergehend nicht verfügbar; wiederholen Sie die Anfrage nach dem Zeitraum aus `Retry-After`. |

## Beispiel

Bewahren Sie das Geheimnis in einer Datei auf, nicht in der Befehlszeile (`oidc.json`):

```json
{"sp_host":"acme.eu1.keenauth.app","issuer":"https://idp.example.com","client_id":"keenauth-acme","client_auth_method":"client_secret_basic","client_secret":"<secret from the identity provider>"}
```

```bash
curl -X PUT "https://api.eu.keenauth.com/v1/connections/conn_01j9xp6q0r1s5t7v9w1x3y5z7b/oidc" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d @oidc.json
```

```bash
keenauth connections oidc put conn_01j9xp6q0r1s5t7v9w1x3y5z7b --data @oidc.json
keenauth connections oidc put conn_01j9xp6q0r1s5t7v9w1x3y5z7b --data @oidc-update.json --if-match '"6f1c…"'
```
