
# Ejecutar un paso de inicio de sesión

`POST /fapi/v1/transactions/current/steps/{step}` · llamado desde el host de inicio de sesión del entorno

Ejecuta un paso de la transacción actual. Esta versión acepta los pasos `identifier` y `password`. Cada paso de credenciales
fallido devuelve el mismo `401 invalid_credentials`, de modo que la respuesta nunca revela si existe una cuenta. Cuando el paso de
la contraseña completa la transacción, se establecen las cookies de sesión `__Host-idp_session` (y, si es necesario,
`__Host-idp_device`) y se elimina la cookie de transacción.

## Solicitud

Encabezados:

| Encabezado | Obligatorio | Descripción |
| --- | --- | --- |
| `Idp-Client` | sí | Identificador del SDK. |
| `Origin` | sí | Debe ser exactamente `https://<sign-in host>`. |
| `Idp-Csrf-Token` | sí | El `csrf_token` del objeto de transacción. |

Ruta: `step`, el nombre del paso (`identifier`, `password`, `sso_start`).

En el paso `otp_send`, `next_steps[].methods` enumera los métodos sin contraseña que permite la política vigente (`email_otp`, `magic_link`); un cliente solo ofrece estos.

Cuerpo (los campos dependen del paso; `next_steps[].fields` los enumera):

| Campo | Tipo | Descripción |
| --- | --- | --- |
| `identifier` | string | Dirección de correo electrónico, número de teléfono o nombre de usuario (paso `identifier`), hasta 320 caracteres. |
| `password` | string | La contraseña (paso `password`), hasta 128 caracteres. |
| `connection_id` | string | Un valor `sso_connections[].connection_id` (paso `sso_start`). |

## Respuesta

`200 OK` con la transacción después del paso. Una transacción `completed` no tiene `csrf_token`.

Cuando el entorno requiere un segundo factor y el usuario aún no tiene ninguno, un usuario que todavía está dentro del `mfa.enrollment_grace_days` del entorno puede iniciar sesión igualmente, y la respuesta `completed` incluye `mfa_enrollment`:
`required_by` (RFC 3339, el fin del período de gracia, calculado por el servidor) y `methods` (`webauthn`, `totp`: los factores que el usuario puede registrar ahora, en el orden de la pantalla). Muestre la fecha y permita que el usuario continúe; el registro se añade en la configuración de la cuenta. El campo está ausente cuando no hay período de gracia, el usuario cumple la política o el registro es obligatorio de inmediato. El `min_acr` de una aplicación y el `acr_values` solicitado nunca se posponen por el período de gracia.

## SSO empresarial (descubrimiento del dominio de inicio)

Cuando el paso `identifier` recibe una dirección de correo electrónico cuyo dominio pertenece a una conexión empresarial, el inicio de sesión continúa con esa conexión. Solo se usa la parte posterior a `@` para el descubrimiento.

- Una conexión: la transacción pasa a `federated_redirect` y la respuesta incluye `redirect_url`, la dirección de inicio del proveedor de identidad. Navegue a esa dirección en la ventana de nivel superior. La dirección contiene un token de un solo uso: no lo almacene ni lo registre.
- Varias conexiones: la transacción permanece en `identifier_pending` y la respuesta enumera `sso_connections`
  (`connection_id`, `display_name`, `protocol`). Muestre `display_name` como texto y envíe la elección del usuario con el paso `sso_start` (`identifier` y `connection_id`). Una conexión que no se ofrece para el dominio devuelve `422 validation_failed`.
- Sin conexión, o si el descubrimiento no está disponible temporalmente: el inicio de sesión normal continúa, de modo que una interrupción nunca bloquea los demás métodos de inicio de sesión. `sso_start` es una elección explícita y devuelve `503 temporarily_unavailable` en su lugar.

Cuando la solicitud de inicio de sesión nombra una organización que requiere SSO, la transacción ofrece solo las conexiones de esa organización: los pasos de contraseña y de código de correo electrónico no se ofrecen, y la clave de acceso solo sigue disponible cuando la organización tiene cuentas de emergencia (break-glass). Crear la transacción ya inicia la única conexión (`federated_redirect` con `redirect_url`) o enumera varias en `sso_connections`; envíe la elección solo con `sso_start` y `connection_id`, `identifier` es opcional aquí. Con este requisito, el descubrimiento no recurre a otros métodos: cuando no se puede acceder al inicio de sesión empresarial, el paso devuelve `503 temporarily_unavailable`. Lo mismo se aplica cuando el dominio del correo electrónico pertenece a una organización que requiere SSO para sus dominios verificados.

Después del proveedor de identidad, el navegador vuelve a `/u/sso/complete` en el host de inicio de sesión; la página alojada finaliza el inicio de sesión.

## Vincular el inicio de sesión empresarial a una cuenta existente

Cuando una conexión empresarial no avala las direcciones de correo electrónico y la dirección que afirma ya está verificada en una cuenta del entorno, el inicio de sesión empresarial no abre una sesión. El navegador vuelve a la página alojada de inicio de sesión con una nueva transacción cuyo objeto incluye `account_link`: `connection_name` y, cuando la conexión pertenece a una organización, `organization_name`. Indique al usuario que ya tiene una cuenta y que debe iniciar sesión en ella para vincular la conexión; nunca nombre la cuenta. En esta transacción `sso_start` y `magic_link` no se ofrecen, y el paso `identifier` no dirige a una conexión empresarial.

El usuario inicia sesión en la cuenta existente con sus propios métodos; si un usuario tiene un segundo factor registrado, se le solicita. El paso que completa la transacción no abre ninguna sesión: la conexión se vincula a la cuenta, y la respuesta es una nueva transacción en `federated_redirect` con `redirect_url` para la misma conexión. Navegue a esa dirección en la ventana de nivel superior; el inicio de sesión empresarial ahora termina como de costumbre. Si no se puede iniciar el inicio de sesión empresarial, la nueva transacción es `identifier_pending` y sigue un inicio de sesión ordinario.

Completar con otra cuenta, sin el segundo factor registrado, o con un inicio de sesión anterior a la solicitud de vinculación, no vincula nada y no abre ninguna sesión: `409 transaction_state_conflict`. Una solicitud de vinculación que haya caducado (10 minutos) o que ya se haya usado devuelve `410 transaction_expired`. Una solicitud de vinculación se usa una sola vez, sea cual sea el resultado. Para rechazarla, llame a `POST /fapi/v1/transactions/current:cancel`.

## Política de la organización

Cuando la solicitud de autorización está vinculada a una organización, la política de inicio de sesión de la organización se vuelve a comprobar después del primer factor y justo antes de abrir la sesión:

- La dirección IP del cliente no está en la lista de permitidos de la organización: `403 ip_not_allowed`.
- Los factores de la transacción no cumplen la política de la organización (un método que la organización no permite, un factor ausente, o una clave de seguridad o clave de acceso fuera de la lista de AAGUID permitidos de la organización): `403 no_allowed_method`.
- No se puede leer la política de la organización: `503 temporarily_unavailable`. El inicio de sesión falla en modo seguro y nunca continúa sin la política.

No se abre ninguna sesión. Un rechazo cuando la transacción se completa elimina la cookie de transacción; un `503` después del primer factor deja la transacción donde estaba, y el paso puede reintentarse. El cuerpo del error nunca nombra la organización, el usuario ni la dirección IP.

## Transacciones headless vinculadas a DPoP

Para una transacción iniciada con un encabezado `DPoP`, envíe una nueva prueba desde la misma clave (`htm` `POST`, `htu` la URL del paso) en lugar de `Idp-Csrf-Token`; no se usa ninguna cookie. El paso que completa la transacción devuelve `authorization_response` una sola vez:

```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"
}
```

Compruebe que `state` y `iss` coinciden, y luego intercambie el código en `/oauth2/token` con su `code_verifier` y una prueba DPoP desde la misma clave. Una prueba de otra clave devuelve `invalid_grant`. Si la solicitud de autorización no puede terminar en un código (se necesita consentimiento, aceptar términos legales, elegir una organización o un nuevo inicio de sesión, o el acceso está denegado), el paso devuelve `403 authorization_failed` y el miembro `error` contiene el código de error de OAuth; no se emite ningún código.

## Errores

| Estado | Código | Cuándo |
| --- | --- | --- |
| 401 | `invalid_credentials` | El identificador o la contraseña no son aceptados. |
| 403 | `origin_not_allowed` | `Origin` o `Idp-Csrf-Token` falta o es incorrecto. |
| 403 | `ip_not_allowed` | La dirección IP del cliente no está en la lista de permitidos de la organización. |
| 403 | `no_allowed_method` | El inicio de sesión no cumple la política de la organización. |
| 403 | `test_feature_not_in_production` | `otp_verify` o `email_2fa` recibió el código de prueba fijo `424242` en un entorno de producción. El intento se cuenta como un código incorrecto. |
| 404 | `not_found` | El nombre del paso no es un paso conocido. |
| 409 | `transaction_state_conflict` | El paso no está disponible en el estado actual. |
| 409 | `session_limit_reached` | El usuario ha alcanzado el límite de sesiones y se deniegan las nuevas sesiones. |
| 410 | `transaction_expired` | La transacción ha terminado. |
| 422 | `validation_failed` | Falta un campo o no es válido. |
| 503 | `temporarily_unavailable` | `sso_start` no pudo conectar con el inicio de sesión empresarial, o no se pudo leer la política de la organización; inténtelo de nuevo. |
| 401 | `invalid_dpop_proof` | La prueba `DPoP` falta, no es válida o se reutilizó. |
| 403 | `authorization_failed` | La transacción vinculada a DPoP se completó, pero su solicitud de autorización terminó sin un código. |

## Ejemplo

```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"}'
```

## Datos personales

Este endpoint contiene datos personales: perfil del usuario final y credenciales. [Datos personales en las API de KeenAuth](/docs/policies/personal-data) describe qué se almacena, cuánto tiempo se conserva y cómo se elimina. No envíe categorías especiales de datos personales (salud, datos biométricos, religión, opiniones políticas, orientación sexual) en ningún campo.
