# 认证和 OAuth

> API 密钥、带 PKCE 的 OAuth 2.1（SMART on FHIR 单独启动）、OpenID Connect id_token、SMART v2 患者范围、令牌生命周期和同意生命周期。

Source: https://developers.anpheros.com/zh/guides/authentication

Anpheros Platform 接受三种凭证。每个请求携带其中一种。

| 凭证 | 外观 | 谁 | 查看 |
|---|---|---|---|
| API 密钥 | `sk_test_…` (沙盒) / `sk_live_…` (生产) | 项目的服务器 | 项目创建的患者（在沙盒中，包括其自身 30 名合成患者的副本） |
| OAuth 访问令牌 | `at_…` | 代表在同意下为一名患者行事的应用程序 | 仅限该患者，在授予的 SMART 范围内 |
| Firebase ID 令牌 | JWT | 在仪表板中的开发者，或在“连接”中的患者 | 其自己的组织/其自己的记录 |

将其作为 `Authorization: Bearer <credential>` 发送（API 密钥也可作为 `X-Api-Key` 工作）。

## API 密钥

- 在仪表盘或通过 `POST /admin/projects/{id}/keys` 创建；仅显示一次；存储为 SHA-256 哈希值。
- 作用域：`read`、`write`。密钥绝不会跨越其项目环境（`sk_test_` 无法访问生产数据，反之亦然）。
- 每个密钥的速率限制（默认为 600/分钟）在整个平台（共享存储）强制执行，并在 429 时有 `Retry-After`。还有一个每 IP 地址的限制为 600/分钟。
- 写入时的可选标头：`X-Anpheros-Author-Type`、`X-Anpheros-Author-Ref`、`X-Anpheros-Source-System`、`X-Anpheros-Origin-Id`、`X-Anpheros-Acting-As`（**您自己目录中的** Practitioner/PractitionerRole）、`X-Anpheros-On-Behalf-Of`（您自己目录中的 Organization）。它们会填充 Provenance。

## OAuth 2.1 (SMART on FHIR, standalone launch)
Discovery: `GET /.well-known/smart-configuration`.

1. `GET /oauth/authorize?response_type=code&client_id=…&redirect_uri=…&scope=…&state=…&code_challenge=…&code_challenge_method=S256[&purpose=treatment][&patient=<pairwise id>][&lang=ro]`
   显示托管的同意页面。PKCE S256 是强制性的；`redirect_uri` 必须精确注册。
2. 患者登录（通过 Firebase 的 Google 或电子邮件），选择记录（自己的或受抚养人的），时长（30/90/180/365 天）并授权。平台会发放一个一次性代码（10 分钟）。
3. `POST /oauth/token` 使用 `grant_type=authorization_code&code=…&code_verifier=…&redirect_uri=…&client_id=…`（机密客户端添加 `client_secret`）。
   响应：`access_token`（30 分钟），`refresh_token`（30 天，轮换），`patient`（您针对该记录的成对 ID），`grant_id`，`scope`。
4. Refresh：`grant_type=refresh_token`。每个刷新令牌只能使用一次。**使用过的刷新令牌会撤销整个链条**（盗窃检测）。刷新请求的并行重复会被拒绝，并可能撤销链条，因此切勿同时轮换。
5. Revoke：`POST /oauth/revoke`（token + client_id）。撤销刷新令牌也会撤销其访问令牌。

令牌响应包含 `Cache-Control: no-store` 和 `Pragma: no-cache`，正如 SMART 所要求的那样。

### OpenID Connect (`openid fhirUser`)
在患者范围之外请求 `openid fhirUser`，并且令牌响应还包含一个 `id_token`：一个使用 RS256 签名的 JWT，其中包含 `iss`（平台的基 URL），`sub`（您针对该人员的成对 ID），`aud`（您的 `client_id`），`exp`，`iat` 和 `fhirUser` — 该人员的 Patient 资源的绝对 URL，可以使用您刚刚收到的访问令牌读取。Discovery 位于 `GET /.well-known/openid-configuration`；公钥位于 `GET /oauth/jwks`（令牌头中的 `kid`）。`nonce` 参数尚不支持（在 authorization-code 流程中它是可选的）。接受 `launch/patient` 和 `offline_access`；令牌响应的 `patient` 字段是启动上下文。

其他授权类型：`client_credentials`（机密客户端；行为类似于 API 密钥），以及第一方身份授权（仅限受信任的客户端）。

### 您的品牌在同意页面上

应用程序可以在托管的同意页面上显示其徽标和强调色。在控制台中设置它们
（Applications → Brand）或使用管理员 API：

```http
PUT /admin/applications/{application_id}/branding
{"logo": "data:image/png;base64,…", "brand_color": "#1D4ED8"}
```

- **Logo：** 一个 PNG、JPEG 或 WebP 图像，作为数据 URI，最大 64 KB。检查的是内容，而不是声明的类型；
  不支持 SVG。图像会与应用程序一起存储并嵌入到页面中，因此同意页面不会向您的服务器发出请求。
- **Accent colour：** `#RRGGBB`，用于主按钮。其上的白色文本必须保持至少 4.5:1 的对比度（WCAG AA）；
  较浅的颜色将被拒绝。
- 您省略的字段将保持不变；`null` 或空字符串会将其删除。

页面的其余部分保持不变：“Secured by Anpheros Platform” 行、应用程序请求内容的普通语言列表以及沙盒项目上的 TEST 横幅将保留，因此人们始终可以知道同意是由 Anpheros 持有的。AI 连接器（MCP）始终显示 Anpheros 页面，不带应用程序品牌。

### Scopes
SMART v2 患者范围：`patient/<Type>.<cruds>`，可选的 `?category=<code>` 过滤器（服务器强制执行的唯一过滤器；任何其他过滤器将在授权时被拒绝）。`patient/*.rs` 读取所有内容；`offline_access` 添加刷新令牌。患者人口统计信息和目录始终可在授权下读取。授权范围之外的资源类型返回 403；授权范围之外的患者返回 404。

### Consent lifecycle
同意会自动过期，患者可以随时撤销（Connections 屏幕 / `/me`），并且在同意下的每次读取都会记录应用程序 ID。Webhooks `consent.granted` / `consent.revoked` 会通知项目。

## 错误

401 unknown/expired credential · 403 the credential exists but may not do this · 404 the resource does not exist *for you* · 429 rate limited (`Retry-After`)。请参阅 [`errors.md`](https://developers.anpheros.com/zh/guides/errors)。
