AnpherosAnpheros PlatformDevelopers

Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card

Как реализовать согласие пациента с SMART on FHIR

Руководство: SMART on FHIR с OAuth 2.1 и PKCE шаг за шагом — обнаружение, регистрация приложения, экран согласия, обмен токенами, принудительное применение областей действия, ротация обновления и отзыв — и что реализовано в Anpheros.

SMART on FHIR — это стандартный способ получения приложением разрешения человека на доступ к его FHIR-записи: OAuth 2.1 с PKCE для авторизации, области действия (scopes), которые точно указывают, что можно читать или записывать, и документ обнаружения (discovery document), который сообщает приложению, куда обращаться. Это учебное пособие пошагово демонстрирует весь процесс работы с Anpheros, включая curl: обнаружение, регистрацию приложения, отправку человека на экран согласия, обмен кодом, вызов API в рамках предоставленных областей действия, обновление и действия при отзыве доступа. Anpheros — это бэкенд SMART on FHIR: он размещает сервер авторизации, экран согласия и сервер FHIR R4, поэтому вам не нужно писать собственный интерфейс входа или согласия.

Почему согласие, а не просто API-ключ

API-ключ предоставляет доступ к данным пациентов, созданным вашим проектом. Существующие записи человека (его собственные данные, собранные другими приложениями, клиниками и лабораториями) он может предоставлять для совместного использования. С помощью SMART on FHIR:

Модель, лежащая в основе этого, описана в Healthcare API with patient consent и Consent and access model.

Шаг 1: обнаружение

curl https://platform.anpheros.com/fhir/R4/.well-known/smart-configuration

Ответ содержит список конечных точек и информацию о том, что поддерживает сервер (сокращенно):

{"issuer": "https://platform.anpheros.com",
 "authorization_endpoint": "https://platform.anpheros.com/oauth/authorize",
 "token_endpoint": "https://platform.anpheros.com/oauth/token",
 "revocation_endpoint": "https://platform.anpheros.com/oauth/revoke",
 "code_challenge_methods_supported": ["S256"],
 "scopes_supported": ["patient/*.rs", "patient/Patient.r", "patient/Observation.rs", "patient/Observation.rs?category=laboratory",
                      "patient/Observation.rs?category=vital-signs", "patient/Observation.c", "patient/Condition.rs",
                      "patient/MedicationStatement.rs", "patient/DocumentReference.rs", "patient/AllergyIntolerance.rs",
                      "offline_access", "launch/patient", "openid", "fhirUser"],
 "capabilities": ["launch-standalone", "client-public", "client-confidential-symmetric", "permission-patient",
                  "permission-offline", "context-standalone-patient", "sso-openid-connect"]}

Клиентские библиотеки SMART считывают этот документ и не требуют дополнительной настройки.

Шаг 2: регистрация вашего приложения

На панели управления откройте ваш проект и добавьте приложение с его URI перенаправления. Или через Admin API:

curl -X POST https://platform.anpheros.com/admin/projects/$PROJECT/applications \
     -H "Authorization: Bearer $FIREBASE_ID_TOKEN" -H "Content-Type: application/json" -d '{
  "name": "CardioAI", "client_type": "public",
  "redirect_uris": ["https://cardio.example/callback"],
  "purpose": "cardiology follow-up", "privacy_url": "https://cardio.example/privacy"
}'
{"id": "app_…", "name": "CardioAI", "client_type": "public", "client_id": "client_Hg6CknNkYlMgN190", "client_secret": null,
 "redirect_uris": ["https://cardio.example/callback"], "purpose": "cardiology follow-up", "status": "active", …}

Используйте public для мобильных и браузерных приложений, которые не могут хранить секрет и полагаются на PKCE. Используйте confidential для сервера; его client_secret отображается один раз. Название, назначение и ссылка на политику конфиденциальности — это то, что пользователь видит на экране согласия.

Шаг 3: Перенаправление пользователя на экран согласия

Создайте пару PKCE. Верификатор остается у вас; передается только его хеш:

VERIFIER=$(openssl rand -base64 64 | tr -d '=+/\n' | cut -c1-64)
CHALLENGE=$(printf %s "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=')

Затем откройте этот адрес в браузере пользователя (переносы строк добавлены для удобства чтения):

https://platform.anpheros.com/oauth/authorize?response_type=code
  &client_id=client_Hg6CknNkYlMgN190
  &redirect_uri=https://cardio.example/callback
  &scope=openid fhirUser patient/Observation.rs?category=laboratory patient/Condition.rs offline_access
  &state=8c1e…               ← a random value you check on return
  &code_challenge=$CHALLENGE&code_challenge_method=S256
  &purpose=treatment&lang=en

Запрашивайте только самое необходимое. Это приложение считывает результаты лабораторных исследований и диагнозы, ничего более. offline_access выдает токен обновления, поэтому пользователю не придется подтверждать согласие каждые 30 минут.

Пользователь входит в Anpheros, читает запрос на понятном языке, выбирает, какую запись предоставить (свою собственную, запись члена семьи, за которым он ухаживает, или запись, созданную вашим приложением для него), и на какой срок предоставляется доступ, затем разрешает или запрещает. Пользователь возвращается по вашему URI перенаправления:

https://cardio.example/callback?code=…&state=8c1e…

Убедитесь, что state соответствует значению, которое вы отправили ранее, прежде чем использовать код.

Шаг 4: обмен кода на токены

curl -X POST https://platform.anpheros.com/oauth/token \
  -d grant_type=authorization_code -d client_id=client_Hg6CknNkYlMgN190 \
  -d code=$CODE -d code_verifier=$VERIFIER -d redirect_uri=https://cardio.example/callback
{"access_token": "at_…", "token_type": "Bearer", "expires_in": 1800,
 "scope": "patient/Observation.rs?category=laboratory patient/Condition.rs openid fhirUser offline_access",
 "patient": "82bfd321-6a4d-4aea-943a-a62f4d81d419", "grant_id": "grant_…",
 "id_token": "eyJ…", "refresh_token": "rt_…"}

Шаг 5: вызов API в рамках разрешений

curl "https://platform.anpheros.com/fhir/R4/Observation?patient=$PATIENT&category=laboratory" -H "Authorization: Bearer $ACCESS_TOKEN"

Результаты лабораторных исследований возвращаются как обычно. Запросите что-то, выходящее за рамки предоставленных разрешений, например, лекарства:

curl "https://platform.anpheros.com/fhir/R4/MedicationStatement?patient=$PATIENT" -H "Authorization: Bearer $ACCESS_TOKEN"
{"resourceType": "OperationOutcome", "issue": [{"severity": "error", "code": "forbidden",
  "diagnostics": "The consent behind this token does not allow 's' on MedicationStatement."}]}

Это 403. Поиски в рамках разрешений также фильтруются: с Observation.rs?category=laboratory поиск всех наблюдений возвращает только лабораторные. Любой другой пациент не существует для этого токена (404). REST-представление (/v1) и контекстный API применяют те же разрешения.

Шаг 6: обновление

Токены доступа действительны в течение 30 минут. Токены обновления действительны в течение 30 дней и ротируются при каждом использовании:

curl -X POST https://platform.anpheros.com/oauth/token \
  -d grant_type=refresh_token -d client_id=client_Hg6CknNkYlMgN190 -d refresh_token=$REFRESH_TOKEN

Вы получаете новый токен доступа и новый токен обновления. Сохраните новый немедленно. Повторное использование старого токена обновления рассматривается как кража: оно завершается ошибкой 400 и отзывает весь грант.

Шаг 7: Отзыв доступа

Пользователь может отозвать ваш доступ из Anpheros в любое время, и вы также можете отозвать его самостоятельно, например, когда пользователь отключается в вашем приложении:

curl -X POST https://platform.anpheros.com/oauth/revoke -d token=$REFRESH_TOKEN -d client_id=client_Hg6CknNkYlMgN190

С этого момента каждый вызов с использованием этого grant будет отвечать 401. Обработайте это, показав пользователю, что соединение завершено, и предложив подключиться снова. Подпишитесь на вебхук consent.revoked, чтобы узнать об этом, не дожидаясь неудачного вызова.

С помощью SDK

TypeScript и Dart SDK выполняют шаги с 3 по 6 за вас: OAuthFlow.authorizeUrl с сгенерированной парой PKCE, exchange при обратном вызове и автоматическое обновление с ротацией. Полные примеры: Как создать приложение для здравоохранения с ИИ и бэкендом FHIR (TypeScript) и Как создать приложение для здравоохранения с Flutter (Dart).

Что реализует Anpheros

Часть SMART В Anpheros
Discovery /.well-known/smart-configuration на базе FHIR, с поддерживаемыми конечными точками, областями действия (scopes) и методами PKCE
Launch автономный запуск (приложение запускается, затем запрашивает доступ); запуск из EHR в рамках клинической системы не предлагается
Authorisation OAuth 2.1 с обязательным PKCE, поток кода авторизации
Scopes пациентские области действия SMART v2, patient/<Resource>.<cruds> с фильтрами по категориям, а также openid и fhirUser
Identity OpenID Connect id_token, называющий пациента как ресурс FHIR
Consent размещенный экран согласия на языке пациента, с продолжительностью, выбранной пациентом, отраженный как FHIR Consent
Tokens 30-минутные токены доступа, ротируемые 30-дневные токены обновления, привязанные к согласию, отзыв
Conformance заявление о возможностях объявляет службу безопасности SMART; группа "Standalone Launch" набора тестов Inferno SMART App Launch STU2 проходит 22 из 22 тестов (запуск от 28 сентября 2026 г.); другие группы и наборы тестов Inferno не запускались

Запись работает так же: запись областей действия (patient/Observation.c, .u, .d) позволяет вашему приложению создавать, обновлять или удалять данные в записи. Все, что записано, несет ваше приложение как автора, повторные попытки с ключом идемпотентности никогда не дублируют измерение, а удаления являются мягкими и сохраняют историю (Medical data API).

Чего еще нет

Эти пункты перечислены вместе с остальными в разделе Версионирование и устаревание, а заявление о возможностях (capability statement) всегда является авторитетным источником.

Часто задаваемые вопросы

Что такое SMART on FHIR?

Открытый стандарт, основанный на OAuth 2.0/2.1 и OpenID Connect, который определяет, как приложение запрашивает доступ к записи FHIR, какие области действия описывают этот доступ и как сервер объявляет свои конечные точки. Любая клиентская библиотека с поддержкой SMART может использовать любой сервер с поддержкой SMART.

Нужен ли мне PKCE?

Да. Anpheros требует PKCE с S256 для каждого потока кода авторизации, как для публичных, так и для конфиденциальных клиентов. Это предотвращает использование перехваченного кода авторизации кем-либо другим.

Что произойдет, если пользователь откажет?

Пользователь вернется на ваш URI перенаправления с error=access_denied и вашим state, но без кода. Объясните, что требуется для этой функции, и позвольте пользователю попробовать снова; вызовы вне предоставленного разрешения всегда возвращают 403.

Может ли родитель дать согласие за ребенка?

Да. На экране согласия пользователь может выбрать запись, о которой он заботится, например, запись ребенка, если она связана с его учетной записью. Предоставленное разрешение применяется только к этой записи.

Связанные материалы

Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card

Product updates by email

New features, guides and the end of the beta. One email a month at most.

Send me occasional Anpheros Platform updates by email (new features, API changes, guides). I'll confirm by email and can unsubscribe in one click from any email. Privacy