> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# 通行密钥、验证码、社交登录与 SSO 登录方式

> Didit 登录方式配置：密码、邮箱验证码、魔法链接、电话验证码、通行密钥、社交登录、企业 SSO、Didit ID Wallet 登录，以及 MFA 和密码重置。

> [!WARNING]
>
> 身份认证功能为新功能。托管登录页面支持本页列出的全部方式。此处列出的 JSON endpoint 供自行构建登录界面的团队使用（`sign_in_ui: "own"`）。

使用 `PUT methods/{name}/` 并传入 `{"enabled": true}`，通过应用的认证管理 API 启用某个方式，或在控制台中启用。托管登录页面只显示您已启用的方式。

| 方式 | 名称 | 设置 |
| - | - | - |
| 密码 | `password` | 使用密码进行邮箱注册时也需要启用。 |
| 邮箱验证码 | `code` | 无。 |
| 魔法链接 | `magic` | 无。仅限托管页面。 |
| 手机验证码 | `phone` | 传入一个包含电话验证的工作流的 `workflow_id`。 |
| 通行密钥 | `passkey` | 无。 |
| 社交登录 | `google`, `microsoft`, `apple`, `github` | 您自己的 `client_id` 和 `client_secret`。沙盒应用可以改用 Didit 的测试应用（`credential_source: "didit_test"`）。 |
| 组织 SSO | `sso` | 每个客户组织一个 SAML 或 OIDC 连接。 |
| Didit ID Wallet | `wallet` | 始终开启，无法关闭。 |

下方每个 JSON 调用都以 `POST authorize/` 返回的 `transaction` 开始。该交易有效期为 10 分钟。登录成功后返回 `{code, redirect_uri, state}`。请在 60 秒内通过 `POST token/` 兑换授权码（参见 [令牌与 JWKS](https://docs.didit.me/zh/authentication/tokens-and-jwks.md)）。

登录调用也可能返回以下步骤，而不是授权码。完成该步骤后，即可获得授权码。

| 响应 | 后续步骤 |
| - | - |
| `mfa_required` 及 `challenge` 和 `factors` | 发送 TOTP 或恢复码，或使用通行密钥（参见 [MFA](#mfa)）。 |
| `mfa_enrollment_required` 及 `challenge` 和 `uri` | MFA 策略要求使用验证器。请使用 `POST mfa/setup/` 注册验证器。 |
| `protection_required` 及 `challenge` 和 `methods` | [机器人防护](https://docs.didit.me/zh/authentication/bot-protection.md)策略要求提供额外的验证。 |
| `verification_required` 及 `verification_url` | 您的验证设置要求在注册或登录时进行活体检测或身份证件验证。请将用户引导至 `verification_url`（有效期 30 分钟）；验证通过后才会返回授权码。 |

## 密码

`POST password/` 接受 `transaction`、`email` 和 `password` 参数。

* 密码必须满足您设置的 `password_min_length`（8、10、12 或 14 个字符；默认为 10 个字符）。常见密码和纯数字密码会以 `password_policy` 被拒绝。开启[泄露密码检查](https://docs.didit.me/zh/authentication/bot-protection.md#泄露密码)后，已知泄露过的密码会以 `password_breached` 被拒绝。
* 只有邮箱已验证的用户才能使用密码登录。
* 密码错误、邮箱不存在、邮箱未验证、账户被锁定以及账户被封禁，都会返回相同的结果：`400 {"error": "invalid_credentials"}`。您的界面无法分辨具体是哪种情况，攻击者也无法分辨。

### 注册

注册时先验证邮箱。使用 `purpose: "signup"`、`email` 和 `password` 调用 `POST email/start/`，然后使用验证码调用 `POST email/complete/`。账户将以已验证的邮箱创建。

* `signup_policy` 决定谁可以注册：`anyone`（任何人）、`invited`（仅限持有邀请链接的用户）或 `allowed_domains`（允许的域名）。
* 当 `allow_subaddresses: false`（默认值）时，本地部分包含 `+` 的邮箱地址会被拒绝。
* 如果您的品牌设置中配置了条款或隐私链接，托管注册表单会要求用户接受这些内容。

## 邮箱验证码

`POST email/start/` 接受 `transaction`、`purpose`（`login` 或 `signup`）和 `email` 参数，并返回 `202 {challenge, expires_in: 600}`。用户将收到一个 6 位数字验证码，有效期为 10 分钟。

`POST email/complete/` 接受 `transaction`、`purpose`、`challenge` 和 `code` 参数。每个验证码共可尝试 5 次，之后用户必须重新请求验证码。托管页面在 30 秒后提供重新获取验证码的选项。

当您的 `signup_policy` 允许时，对于没有账户的邮箱地址，登录验证码会自动创建账户。这就是无密码注册。

## 魔法链接

托管页面会发送一个有效期为 15 分钟的登录链接。该链接始终绑定于最初的 PKCE 交易，因此只能在发起它的流程中使用。用户需要在链接打开的页面上确认登录。魔法链接没有对应的 JSON endpoint。

## 手机验证码

`POST phone/start/` 接受 `transaction`、`phone` 和可选的 `channel` 参数（默认为 `sms`，也可以是 `whatsapp`）。手机号会被规范化为 E.164 格式。该接口返回 `202 {challenge, expires_in: 600}`。

`POST phone/complete/` 接受 `transaction`、`challenge` 和 6 位数字 `code` 参数。每个验证码共可尝试 5 次。

* 手机验证码通过 Didit 的电话验证发送。请使用包含电话验证的工作流的 `workflow_id` 启用该方式。
* 只有当 `signup_policy` 为 `anyone` 时，用户首次使用手机登录才会创建账户。
* 如果发送失败，调用将返回 `503 {"error": "delivery_unavailable"}`。

## 通行密钥

通行密钥基于 WebAuthn。信赖方是您应用的登录源。Didit 请求可发现凭据（resident key），并始终要求用户验证，例如指纹、人脸或设备 PIN。Didit 不请求证明（attestation）。

| 调用 | 请求体 | 结果 |
| - | - | - |
| `POST passkeys/begin/` | `{transaction}` | 返回用于 `navigator.credentials.get()` 的 `{challenge, options}`。不会发送凭据列表，因此浏览器会提供与您的源关联的所有通行密钥。 |
| `POST passkeys/complete/` | `{challenge, credential}` | 授权码，或后续步骤。 |
| `POST passkeys/register/` | 为空，并附带 `Authorization: Bearer <access_token>` | 返回用于 `navigator.credentials.create()` 的选项。 |
| `POST passkeys/confirm/` | `{challenge, credential}`，并使用同一令牌 | 新通行密钥的 `{id}`。 |

* 通行密钥挑战有效期为 5 分钟。
* 添加通行密钥需要会话在过去 5 分钟内创建。否则调用将返回 `403 {"error": "reauthentication_required"}`。请先让用户重新登录。
* 通行密钥登录计为多因素认证。
* 注册完成后，托管页面会提供添加通行密钥的选项（`passkeys/setup/begin/` 和 `passkeys/setup/complete/`）。
* 在该应用中注册的 Android 应用可以使用相同的通行密钥。

## 社交登录

Google、Microsoft、Apple 和 GitHub 登录使用你自己的 OAuth 应用凭据，通过 `PUT methods/{provider}/` 和 `credentials: {client_id, client_secret}` 进行设置。提供商的回调地址位于你的登录来源上。

用户首次使用某个提供商登录时，还需通过验证码证明其拥有该邮箱地址（`POST social/email/start/` 和 `POST social/email/verify/`）。之后使用该提供商登录时，将跳过此步骤。

GitHub 无法证明近期的登录行为，因此当你发送 `prompt=login` 或 `max_age` 时，不会提供 GitHub 登录选项。

## 组织 SSO

组织 SSO 允许客户公司通过其自有的 SAML 或 OIDC 身份提供商登录。请为每个客户组织在 `organizations/{id}/sso/` 进行配置，设置 `protocol`（`saml` 或 `oidc`）、`enabled` 和 `config`。

* 你可以向客户的 IT 团队发送有效期为 7 天的设置链接。
* 你的 SAML 服务提供商元数据发布在 `{origin}/sso/saml/metadata/`。
* 托管登录页会根据用户已验证的邮箱域名，或登录 URL 中的 `organization=<slug>`，查找对应的连接配置。

## Didit ID Wallet

已在 Didit 完成验证的用户可以使用其 Didit ID Wallet 登录。此方式始终开启。会话中的 `verified_identity` 随后会包含该用户选择分享的信息。

## MFA

第二因素为身份验证器应用（TOTP）加恢复码，或通行密钥。

* `mfa_policy` 决定谁必须使用 MFA：`optional`、`everyone` 或 `organization_admins`（默认值）。已注册身份验证器的用户必须始终使用它。
* 要注册身份验证器，请使用新会话（会话须在 5 分钟内创建）调用 `POST mfa/enroll/`。它返回 `{challenge, uri}`；将 `uri` 显示为二维码。然后将第一个验证码发送至 `POST mfa/confirm/`。响应中包含 10 个仅可使用一次的恢复码。请只展示一次。
* 登录时，携带 `challenge` 将 TOTP 或恢复码发送至 `POST mfa/complete/`。你有 5 次尝试机会。若要改用通行密钥，请调用 `POST mfa/passkey/begin/` 和 `POST mfa/passkey/complete/`。
* 验证码以 30 秒为一个时间步长。已被接受的验证码不能再次使用。
* 短信验证码和邮箱验证码不可用作第二因素。

## 忘记和重置密码

`POST password-reset/start/` 接收 `email`，并返回 `202 {"status": "sent", "expires_in": 1800}`。无论该邮箱地址是否有对应账户，返回结果都相同。重置链接有效期为 30 分钟。

`POST password-reset/complete/` 接收 `token` 和 `password`，并返回 `{"status": "password_changed"}`。此接口还会：

* 清除锁定状态，
* 当 `revoke_on_password_change` 开启（默认）时，结束所有会话，
* 使该用户其他待处理的验证码和链接失效。

## 邀请

当 `signup_policy: "invited"` 时，只有受邀用户可以注册。邀请链接有效期为 7 天，打开的是托管的 `/invite` 页面。

继续阅读[token 与 JWKS](https://docs.didit.me/zh/authentication/tokens-and-jwks.md)，或阅读[机器人防护](https://docs.didit.me/zh/authentication/bot-protection.md)了解锁定和挑战。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.