# Аутентификация и OAuth

> API ключи, OAuth 2.1 с PKCE (автономный запуск SMART on FHIR), OpenID Connect id_token, области действия SMART v2 для пациентов, время жизни токенов и жизненный цикл согласия.

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

Платформа Anpheros принимает три типа учетных данных. Каждый запрос несет ровно одно.

| Учетные данные | Выглядят как | Кто | Видит |
|---|---|---|---|
| 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.
- Области действия (Scopes): `read`, `write`. Ключ никогда не выходит за пределы среды своего проекта (`sk_test_` не может получить доступ к производственным данным и наоборот).
- Ограничение скорости для каждого ключа (по умолчанию 600 запросов в минуту) применяется в масштабах всей платформы (общая база данных), с `Retry-After` при ответе 429. Также существует ограничение в 600 запросов в минуту на IP-адрес.
- Необязательные заголовки при записи: `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. Пациент входит в систему (через Google или электронную почту Firebase), выбирает запись (свою или зависимого лица), срок действия (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` (ваш парный идентификатор для записи), `grant_id`, `scope`.
4. Обновление: `grant_type=refresh_token`. Каждый токен обновления используется один раз. **Предъявление использованного токена обновления отзывает всю цепочку** (обнаружение кражи). Параллельный дубликат запроса на обновление отклоняется и также может отозвать цепочку, поэтому никогда не выполняйте ротацию одновременно.
5. Отзыв: `POST /oauth/revoke` (токен + client_id). Отзыв токена обновления также отзывает его токены доступа.

Ответы токенов содержат `Cache-Control: no-store` и `Pragma: no-cache`, как того требует SMART.

### OpenID Connect (`openid fhirUser`)
Запрашивайте `openid fhirUser` наряду с областями действия пациента, и ответ токена также будет содержать `id_token`: JWT, подписанный с помощью RS256, с `iss` (базовый URL платформы), `sub` (ваш парный идентификатор для человека), `aud` (ваш `client_id`), `exp`, `iat` и `fhirUser` — абсолютный URL ресурса Patient человека, доступный для чтения с помощью полученного вами токена доступа. 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"}
```

- **Логотип:** изображение в формате PNG, JPEG или WebP в виде URI данных, размером до 64 КБ. Проверяется содержимое, а не заявленный тип;
  SVG не принимается. Изображение хранится вместе с приложением и встраивается на страницу, поэтому страница согласия
  не делает запросов к вашим серверам.
- **Акцентный цвет:** `#RRGGBB`, используется для основной кнопки. Белый текст на нем должен сохранять контрастность не менее
  4,5:1 (WCAG AA); более светлые цвета отклоняются.
- Поле, которое вы не указываете, остается без изменений; `null` или пустая строка удаляют его.

Остальная часть страницы не меняется: строка "Secured by Anpheros Platform", список простым языком того,
что запрашивает приложение, и баннер TEST на тестовых проектах остаются, поэтому люди всегда могут понять,
что согласие управляется Anpheros. AI-коннекторы (MCP) всегда отображают страницу Anpheros без брендинга приложения.

### Области действия (Scopes)
Области действия пациента SMART v2: `patient/<Type>.<cruds>` с необязательным фильтром `?category=<code>` (единственный фильтр, который enforces сервер; любой другой фильтр отклоняется во время авторизации). `patient/*.rs` читает все; `offline_access` добавляет токен обновления. Демографические данные пациента и каталог всегда доступны для чтения в рамках предоставленного доступа. Тип ресурса вне области действия возвращает 403; пациент вне области действия возвращает 404.

### Жизненный цикл согласия
Согласия истекают автоматически, могут быть отозваны пациентом в любое время (экран "Connections" / `/me`), и каждое чтение в рамках согласия регистрируется с идентификатором приложения. 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/ru/guides/errors).
