
# サインインのステップを実行

`POST /fapi/v1/transactions/current/steps/{step}` · 環境のサインインホストから呼び出されます

現在のトランザクションの1つのステップを実行します。このバージョンでは`identifier`および`password`のステップを受け付けます。認証情報のステップが失敗すると、いずれも同じ`401 invalid_credentials`を返すため、レスポンスからアカウントの存在は分かりません。パスワードのステップでトランザクションが完了すると、セッションCookie `__Host-idp_session`（必要な場合は`__Host-idp_device`も）が設定され、トランザクションCookieは削除されます。

## リクエスト

ヘッダー:

| ヘッダー | 必須 | 説明 |
| --- | --- | --- |
| `Idp-Client` | はい | SDK の識別子。 |
| `Origin` | はい | 正確に `https://<sign-in host>` である必要があります。 |
| `Idp-Csrf-Token` | はい | トランザクションオブジェクトの `csrf_token`。 |

パス: `step`。ステップ名（`identifier`、`password`、`sso_start`）。

`otp_send` ステップでは、`next_steps[].methods` に、有効なポリシーが許可しているパスワードレス方式（`email_otp`、`magic_link`）が一覧されます。クライアントはこれらのみを提示します。

ボディ（フィールドはステップによって異なります。`next_steps[].fields` に一覧があります）:

| フィールド | 型 | 説明 |
| --- | --- | --- |
| `identifier` | string | メールアドレス、電話番号またはユーザー名（`identifier` ステップ）。最大320文字。 |
| `password` | string | パスワード（`password` ステップ）。最大128文字。 |
| `connection_id` | string | `sso_connections[].connection_id` の値（`sso_start` ステップ）。 |

## レスポンス

ステップ実行後のトランザクションを含む `200 OK` を返します。`completed` のトランザクションには `csrf_token` がありません。

環境で第2要素が必須で、ユーザーがまだ一つも登録していない場合でも、環境の`mfa.enrollment_grace_days`内にいるユーザーはサインインでき、`completed` レスポンスには `mfa_enrollment` が含まれます: `required_by`（RFC 3339形式、猶予期間の終了時刻。サーバーが計算します）と`methods`（`webauthn`、`totp`: ユーザーが今登録できる要素を画面上の順序で示したもの）。日付を表示し、ユーザーが続行できるようにしてください。登録はアカウント設定で追加されます。猶予期間がない場合、ユーザーがポリシーを満たしている場合、または登録がすぐに必要な場合は、このフィールドは含まれません。アプリケーションの`min_acr`と要求された`acr_values`は、猶予期間によって延期されることはありません。

## 企業SSO（ホームレルム検出）

`identifier` ステップで、ドメインが企業接続に属するメールアドレスを受け取った場合、サインインはその接続で続行されます。検出に使われるのは`@`より後の部分のみです。

- 接続が1つの場合: トランザクションは`federated_redirect`に移行し、レスポンスには`redirect_url`（ID プロバイダの開始アドレス）が含まれます。トップレベルのウィンドウをそのアドレスに移動してください。このアドレスにはワンタイムトークンが含まれるため、保存もログ記録もしないでください。
- 接続が複数の場合: トランザクションは`identifier_pending`のままとなり、レスポンスには`sso_connections`（`connection_id`、`display_name`、`protocol`）が一覧されます。`display_name`をテキストとして表示し、ユーザーの選択を`sso_start`ステップ（`identifier`と`connection_id`）で送信してください。そのドメインに提供されていない接続を指定すると、`422 validation_failed`が返されます。
- 接続がない場合、または検出が一時的に利用できない場合: 通常のサインインが続行されるため、障害によって他のサインイン方式がブロックされることはありません。`sso_start` は明示的な選択であり、代わりに`503 temporarily_unavailable` を返します。

サインインリクエストでSSOを必須とする組織が指定されている場合、トランザクションはその組織の接続のみを提供します。パスワードおよびメールの認証コードのステップは提供されず、パスキーは組織に緊急用（break-glass）アカウントがある場合にのみ利用可能なままとなります。トランザクションを作成すると、唯一の接続がすでに開始されます（`federated_redirect` と `redirect_url` の組み合わせ）、または`sso_connections` に複数の接続が一覧されます。選択は`sso_start` と `connection_id` のみで送信してください。ここでは`identifier` は任意です。この要件の下では、検出は他の方式にフォールバックしません。企業サインインに到達できない場合、ステップは`503 temporarily_unavailable` を返します。メールドメインが、認証済みドメインに対してSSOを必須とする組織に属している場合も同様です。

IDプロバイダでの認証後、ブラウザはサインインホストの`/u/sso/complete`に戻ります。ホスト型のページがサインインを完了させます。

## 企業サインインを既存のアカウントにリンクする

企業接続がメールアドレスを保証せず、その接続が主張するアドレスが環境内のアカウントですでに認証済みである場合、企業サインインはセッションを開きません。ブラウザは、オブジェクトに`account_link` を含む新しいトランザクションとともにホスト型のサインインページに戻ります: `connection_name` と、接続が組織に属する場合は`organization_name` です。ユーザーにすでにアカウントがあり、接続をリンクするにはそのアカウントにサインインする必要があることを伝えてください。アカウント名は示さないでください。このトランザクションでは`sso_start` と `magic_link` は提供されず、`identifier` ステップは企業接続にルーティングされません。

ユーザーは既存のアカウントに、そのアカウントの方式でサインインします。第2要素を登録しているユーザーには、その入力が求められます。トランザクションを完了させるステップではセッションは開かれません。接続はアカウントにリンクされ、レスポンスは、同じ接続に対する`redirect_url` を含む`federated_redirect` の新しいトランザクションになります。トップレベルのウィンドウをそこに移動してください。企業サインインは通常どおり完了します。企業サインインを開始できない場合、新しいトランザクションは`identifier_pending` となり、通常のサインインが続きます。

別のアカウントで、登録済みの第2要素を使わずに、またはリンク要求より前に行われたサインインで完了した場合、何もリンクされず、セッションも開かれません: `409 transaction_state_conflict`。期限切れ（10分）またはすでに使用されたリンク要求は`410 transaction_expired` を返します。リンク要求は結果にかかわらず一度だけ使用されます。辞退するには`POST /fapi/v1/transactions/current:cancel` を呼び出してください。

## 組織のポリシー

認可リクエストが組織に紐づいている場合、組織のサインインポリシーは、第1要素の後、セッションを開く直前に再度確認されます:

- クライアントのIPアドレスが組織の許可リストに含まれていない場合: `403 ip_not_allowed`。
- トランザクションの要素が組織のポリシーを満たさない場合（組織が許可していない方式、要素の欠落、または組織のAAGUID許可リストに含まれないセキュリティキーもしくはパスキー）: `403 no_allowed_method`。
- 組織のポリシーを読み取れない場合: `503 temporarily_unavailable`。サインインはフェイルクローズドとなり、ポリシーなしで続行されることはありません。

セッションは開かれません。トランザクション完了時の拒否はトランザクションCookieを削除します。第1要素の後の`503` はトランザクションをそのままの状態にし、ステップは再試行できます。エラー本文には、組織、ユーザー、IPアドレスのいずれも示されません。

## DPoPに紐づくヘッドレストランザクション

`DPoP` ヘッダーで開始されたトランザクションでは、`Idp-Csrf-Token` の代わりに、同じ鍵から新しい証明（`htm` `POST`、`htu` はステップのURL）を送信してください。Cookieは使用されません。トランザクションを完了させるステップは、`authorization_response` を一度だけ返します:

```json
{
  "state": "completed",
  "authorization_response": { "code": "<code>", "state": "<your state>", "iss": "https://example.keenauth.app" },
  "next_steps": [],
  "schema_version": 1,
  "expires_at": "2026-11-02T10:15:00Z"
}
```

`state` と`iss` が一致することを確認してから、同じ鍵によるDPoP証明とともに、`/oauth2/token` でコードを`code_verifier` と交換してください。別の鍵による証明は`invalid_grant` を返します。認可リクエストがコードで終了できない場合（同意、法的規約、組織の選択、または新しいサインインが必要な場合、もしくはアクセスが拒否された場合）、ステップは`403 authorization_failed` を返し、`error` メンバーにOAuthのエラーコードが含まれます。コードは発行されません。

## エラー

| ステータス | コード | 発生条件 |
| --- | --- | --- |
| 401 | `invalid_credentials` | 識別子またはパスワードが受け付けられません。 |
| 403 | `origin_not_allowed` | `Origin` または`Idp-Csrf-Token` が欠落している、または誤っています。 |
| 403 | `ip_not_allowed` | クライアントのIPアドレスが組織の許可リストに含まれていません。 |
| 403 | `no_allowed_method` | サインインが組織のポリシーを満たしていません。 |
| 403 | `test_feature_not_in_production` | 本番環境で、`otp_verify` または`email_2fa` が固定のテスト用コード`424242` を受け取りました。試行は誤ったコードと同様にカウントされます。 |
| 404 | `not_found` | ステップ名が既知のステップではありません。 |
| 409 | `transaction_state_conflict` | 現在の状態ではそのステップは利用できません。 |
| 409 | `session_limit_reached` | ユーザーがセッション上限に達し、新しいセッションが拒否されています。 |
| 410 | `transaction_expired` | トランザクションが終了しています。 |
| 422 | `validation_failed` | フィールドが欠落しているか無効です。 |
| 503 | `temporarily_unavailable` | `sso_start` が企業サインインに到達できなかったか、組織のポリシーを読み取れませんでした。再試行してください。 |
| 401 | `invalid_dpop_proof` | `DPoP` の証明が欠落している、無効である、または再利用されています。 |
| 403 | `authorization_failed` | DPoPに紐づくトランザクションは完了したものの、その認可リクエストがコードなしで終了しました。 |

## 例

```bash
curl -X POST https://example.keenauth.app/fapi/v1/transactions/current/steps/identifier \
  -H "Idp-Client: my-app/1.0.0 (node/22.0.0)" \
  -H "Origin: https://example.keenauth.app" \
  -H "Idp-Csrf-Token: $CSRF_TOKEN" \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{"identifier":"jane@example.com"}'
```

## 個人データ

このエンドポイントは個人データ（エンドユーザーのプロフィールと認証情報）を扱います。[KeenAuth APIにおける個人データ](/docs/policies/personal-data)では、保存される内容、保存期間、削除方法について説明しています。いかなるフィールドにも、特別な種類の個人データ（健康、生体データ、宗教、政治的意見、性的指向）を送信しないでください。
