
# 接続のOIDC設定を作成または置き換える

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

エンタープライズOIDC接続のリライングパーティ設定を作成するか、全体を置き換えます。

- **初回の書き込み:** `If-Match` ヘッダーは送信せず、`sp_host`（この環境の有効なホスト）を指定してください。以降、コールバック `https://<sp_host>/sso/<connection_id>/callback` は固定されます。レスポンスは `201 Created` です。設定が存在しない状態で `If-Match` を送信すると、`412` で失敗します。
- **更新:** `If-Match` が必要です。指定しない場合は `428` で失敗し、何も書き込まれません。そのため、ヘッダーなしのリクエストで既存の設定を上書きすることはありません。読み取り後に設定が変更されていた場合（または値が一致しない場合）、リクエストは `412` で失敗します。`*` は現在の設定に一致します。`sp_host` は空にするか、保存されているホストと同じ値にする必要があります。

クライアントシークレットは書き込み専用です。返却、ログ出力、監査ログへの記録は行われません。`client_secret` を指定せずに更新すると、保存済みのシークレットは保持されます。`private_key_jwt` を指定すると、シークレットは削除されます（クライアントアサーションの署名には環境の署名鍵が使われます）。`issuer` を変更すると、保存済みのディスカバリードキュメントは消去されます。`issuer` または `client_id` を変更すると、直前に成功した接続テストは無効になります。同じ設定を送信しても、何も書き込まれません。書き込みは、`connection.protocol_config_created` または `connection.oidc_config_updated` として記録されます（変更されたフィールドのみ。シークレットは `client_secret_set` としてのみ記録されます）。

**有効な**接続では、`issuer` または `client_id` を変更する更新は適用されません。リクエスト全体（新しいシークレットを含む）は[下書きリビジョン](../connections/revisions.md)になります。レスポンスは `200 OK` で、未変更の公開中の設定、変更されていない `ETag`、および `revision` フィールドを返します。下書きは `revision_id` を指定して [接続をテストする](../connections/test.md)で検証し、その後[公開](../connections/publish-revision.md)してください。その他の更新は直接適用されます。

## リクエスト

| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| `connection_id` | path | はい | エンタープライズOIDC接続のID（`conn_…`）。 |
| `If-Match` | header | 更新時 | 前回の読み取りまたは書き込みで取得した `ETag`。更新時に未指定の場合は `428`、古い場合は `412` になります。初回の書き込みでは送信しません。 |
| `sp_host` | string | 初回の書き込み時 | この環境の有効なホスト（小文字）。更新時は空にするか、保存されているホストと同じ値にします。 |
| `issuer` | string | はい | クエリやフラグメントを含まない絶対 `https` URL。最大512バイト。 |
| `client_id` | string | はい | 1〜255バイト。制御文字は使用できません。 |
| `client_auth_method` | string | はい | `private_key_jwt`（推奨。シークレットは保存されません）、`client_secret_basic`、または `client_secret_post`。 |
| `client_secret` | string | いいえ | 書き込み専用。最大1024バイト。更新時に省略すると保持されます。`private_key_jwt` では使用できません。 |
| `client_secret_expires_at` | string \| null | いいえ | IDプロバイダーがシークレットを失効させる日時（RFC 3339）。`client_secret` と併せてのみ指定できます。 |
| `provider_profile` | string | いいえ | `entra`、`okta`、`google`、`keycloak`、`ping`、`onelogin`、`jumpcloud`、または `generic`（デフォルト）。 |
| `entra_tenant_id` | string | `entra` の場合 | Microsoft EntraのテナントID（UUID）。`entra` プロファイルでのみ使用します。 |

## レスポンス

初回の書き込みでは `201 Created`、更新では `200 OK` を返します。設定（[OIDC設定を取得する](get.md)を参照）と新しい `ETag` を含みます。クライアントシークレットはレスポンスに含まれません。更新が下書きリビジョンになった場合、本文には下書きの `revision` も含まれます。この場合、設定と `ETag` は公開中のものです。

## エラー

| HTTP | code | 発生条件 |
|---|---|---|
| 404 | `not_found` | この環境に接続が存在しないか、エンタープライズ接続ではありません。 |
| 409 | `conflict` | 接続がOIDC接続ではないか、`sp_host` が保存されているホストと異なるか、シークレットを使う認証方式で保存済みまたは指定されたシークレットがありません。 |
| 412 | `precondition_failed` | `If-Match` が現在のバージョンと一致しないか、設定が同時に変更されたか、初回の書き込み前に `If-Match` が送信されました。 |
| 422 | `validation_failed` | フィールドが上記のルールに違反しています。`errors[]` がフィールドを示します（`/issuer`、`/client_id`、`/client_auth_method`、`/client_secret`、`/client_secret_expires_at`、`/provider_profile`、`/entra_tenant_id`、`/sp_host`）。 |
| 428 | `precondition_required` | 設定は存在しますが、`If-Match` ヘッダーがありません。 |
| 400 | `unknown_field` | 本文に不明なフィールドが含まれています。 |
| 401 | `unauthenticated` | 認証情報が未指定、無効、または取り消されています。 |
| 403 | `insufficient_permissions` | 認証情報に必要な権限がありません。 |
| 429 | `rate_limited` | レート制限を超えました。`Retry-After` の期間が経過してから再試行してください。 |
| 503 | `service_unavailable` | 依存先サービスが一時的に利用できません。`Retry-After` の期間が経過してから再試行してください。 |

## 例

シークレットはコマンドラインではなくファイル（`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…"'
```
