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、読み取りまたは書き込み可能な内容を正確に示すスコープ、そしてアプリケーションが行くべき場所を伝えるディスカバリ ドキュメントを使用します。 このチュートリアルでは、ディスカバリ、アプリケーションの登録、同意画面への個人送信、コードの交換、付与されたスコープ内での API 呼び出し、リフレッシュ、そして個人がアクセスを失効させた場合に何が起こるか、といった全フローを Anpheros に対してステップバイステップで実行します curl。Anpheros は SMART on FHIR バックエンドであり、認可サーバー、同意画面、および FHIR R4 サーバーをホストするため、独自のログイン UI や同意 UI を記述する必要はありません。
同意が必要な理由(APIキーだけでは不十分な理由)
APIキーは、あなたのプロジェクトが作成した患者に到達します。個人の既存の記録(他のアプリ、クリニック、研究所によって収集された自身のデータ)は、共有するものです。SMART on FHIRを使用すると、以下のことが可能になります。
- 患者は、どのアプリケーションが、何のために、どのくらいの期間、何を読み書きしたいのかを、自身の言語で確認できます。
- あなたのアプリケーションは、そのリソースタイプとアクションのみを取得し、その1つの記録に対してのみアクセスできます。
- すべてのアクセスは記録され、患者がいつでも取り消すことができます。
- 同意は、FHIR
Consentリソースとしても保存されます。
その背後にあるモデルについては、患者の同意を得たヘルスケアAPI および 同意とアクセスモデル で説明されています。
ステップ 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 '=')
次に、以下のURLをユーザーのブラウザで開きます(読みやすくするために改行を追加しています)。
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_…"}
scopeは、許可された内容をリストします。トークンと共に保持し、対象となる機能のみを表示します。patientは、アプリケーションのレコード ID です。これはペアワイズであり、別のアプリケーションでは同じ人物が異なる ID で表示されます。id_tokenは OpenID Connect トークンであり、そのfhirUserクレームが患者リソースの名前を指定します。- コードは一度だけ機能し、一致する
code_verifierとのみ機能します。
ステップ 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
それ以降、そのグラントを使用したすべての呼び出しは 401 を返します。ユーザーに接続が終了したことを示し、再接続を提案することで対応してください。失敗した呼び出しを待たずに通知を受け取るには、consent.revoked Webhook を購読してください。
SDK を使用する場合
TypeScript および Dart SDK は、ステップ 3 から 6 を自動的に実行します。具体的には、OAuthFlow.authorizeUrl で生成された PKCE ペアを使用し、exchange でコールバックを処理し、自動的なリフレッシュとローテーションを行います。完全な例は以下のとおりです。FHIR バックエンドを使用した AI ヘルスケア アプリの構築方法 (TypeScript) および Flutter を使用したヘルスケア アプリの構築方法 (Dart) を参照してください。
Anpheros の実装内容
| SMART の一部 | Anpheros での実装 |
|---|---|
| Discovery | FHIR ベースの /.well-known/smart-configuration。サポートされているエンドポイント、スコープ、PKCE メソッドが含まれます。 |
| Launch | スタンドアロン起動 (アプリケーションが起動し、アクセスを要求します)。EHR からの起動は提供されません。 |
| Authorisation | OAuth 2.1 (PKCE 必須)、認可コードフロー。 |
| Scopes | SMART v2 患者スコープ、カテゴリフィルター付きの patient/<Resource>.<cruds>、および openid と fhirUser。 |
| Identity | 患者を FHIR リソースとして指定する OpenID Connect id_token。 |
| Consent | 患者の言語で表示されるホストされた同意画面。期間は患者が選択し、FHIR Consent としてミラーリングされます。 |
| Tokens | 30 分のアクセストークン、同意にバインドされたローテーションする 30 日間のリフレッシュトークン、取り消し。 |
| Conformance | 機能ステートメントで SMART セキュリティサービスが宣言されています。「Standalone Launch」グループの Inferno SMART App Launch STU2 テストキットは、22 件中 22 件のテストに合格しています (2026 年 9 月 28 日実行)。その他の Inferno グループおよびテストキットは実行されていません。 |
書き込みも同様です。スコープ (patient/Observation.c、.u、.d) を使用すると、アプリケーションはレコードの作成、更新、または削除を行うことができます。書き込まれたすべての内容は、アプリケーションを著者として記録し、冪等性キーを使用したリトライは測定値を重複させず、削除はソフトであり履歴を保持します (Medical data API)。
まだ実装されていない機能
- EHR起動(病院システム内から起動コンテキスト付きでアプリケーションが開かれること)。
- バックエンドサービス用の
system/スコープ。組織では代わりにAPIキーを使用しています。 - バルクデータエクスポート(
$export)。患者単位の$everythingは利用可能です。
これらはバージョン管理と非推奨で他の項目と共にリストされており、機能ステートメントが常に権威ある情報源となります。
よくある質問
SMART on FHIRとは何ですか?
OAuth 2.0/2.1およびOpenID Connectを基盤としたオープンスタンダードであり、アプリケーションがFHIRレコードへのアクセスを要求する方法、そのアクセスを記述するスコープ、およびサーバーがエンドポイントをどのように広告するかを定義します。SMART対応のクライアントライブラリは、SMART対応のサーバーであればどれでも使用できます。
PKCEは必要ですか?
はい。Anpherosでは、パブリッククライアントと機密クライアントの両方で、すべての認可コードフローにS256と共にPKCEが必要です。これにより、傍受された認可コードが他の誰かに使用されるのを防ぎます。
ユーザーが拒否した場合どうなりますか?
ユーザーはerror=access_deniedとstateと共にリダイレクトURIに戻ってきますが、コードはありません。機能が必要とするものを説明し、再試行させてください。許可外の呼び出しは常に403を返します。
親は子供の代わりに同意できますか?
はい。同意画面で、ユーザーはアカウントにリンクされている場合、子供のものなど、関心のあるレコードを選択できます。付与される許可はそのレコードにのみ適用されます。
関連情報
- 認証とOAuth: API キー、トークン、および有効期間の詳細
- 患者の同意を得たヘルスケア API: 同意がアプリケーションの設計にどのような変更をもたらすか
- 同意とアクセスモデル
- FHIR プラットフォーム
- ヘルスケアアプリの構築
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card