# كيفية تطبيق موافقة المريض مع SMART on FHIR

> دليل تعليمي: SMART on FHIR مع OAuth 2.1 و PKCE خطوة بخطوة — الاكتشاف، تسجيل التطبيق، شاشة الموافقة، تبادل الرمز المميز، النطاقات المطبقة، دوران التحديث والإلغاء — وما يطبقه Anpheros.

Source: https://developers.anpheros.com/ar/guides/smart-on-fhir-backend

**SMART on FHIR هي الطريقة القياسية التي يحصل بها التطبيق على إذن الشخص للوصول إلى سجله في FHIR: OAuth 2.1 مع PKCE للمصادقة، ونطاقات تحدد بالضبط ما يمكن قراءته أو كتابته، ومستند اكتشاف يخبر التطبيق إلى أين يذهب.** هذا الدليل التعليمي يشغل التدفق بأكمله مقابل Anpheros، خطوة بخطوة مع `curl`: الاكتشاف، تسجيل تطبيق، إرسال الشخص إلى شاشة الموافقة، تبادل الرمز، استدعاء API ضمن النطاقات الممنوحة، التحديث، وما يحدث عندما يلغي الشخص الوصول. Anpheros هو الواجهة الخلفية لـ SMART on FHIR: فهو يستضيف خادم المصادقة، وشاشة الموافقة، وخادم FHIR R4، لذلك لا تحتاج إلى كتابة واجهة مستخدم تسجيل دخول أو موافقة خاصة بك.

## لماذا الموافقة وليس مجرد مفتاح API

يصل مفتاح API إلى المرضى الذين أنشأ مشروعك لهم. السجل الحالي للشخص (بياناته الخاصة، التي تم جمعها بواسطة تطبيقات وعيادات ومختبرات أخرى) هو ملكه للمشاركة. مع SMART on FHIR:

- يرى الشخص، بلغته، التطبيق الذي يطلب، وماذا يريد قراءته أو كتابته، ولأي غرض ومدة؛
- يحصل تطبيقك فقط على أنواع الموارد والإجراءات تلك، وفقط لهذا السجل الواحد؛
- يتم تسجيل كل وصول ورؤيته من قبل الشخص، الذي يمكنه إلغاؤه في أي وقت؛
- يتم أيضًا تخزين المنحة كمورد FHIR `Consent`.

النموذج الكامن وراء ذلك موصوف في [واجهة برمجة تطبيقات الرعاية الصحية بموافقة المريض](https://developers.anpheros.com/ar/guides/healthcare-api-patient-consent) و [نموذج الموافقة والوصول](https://developers.anpheros.com/ar/guides/consent).

## الخطوة 1: الاكتشاف

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

تسرد الاستجابة نقاط النهاية وما يدعمه الخادم (مقتطف):

```json
{"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: تسجيل تطبيقك

في [لوحة التحكم](https://platform.anpheros.com/dashboard/)، افتح مشروعك وأضف تطبيقًا مع عنوان URI الخاص بإعادة التوجيه الخاص به. أو عبر واجهة برمجة تطبيقات المسؤول (Admin API):

```bash
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"
}'
```

```json
{"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. يبقى المُتحقق معك؛ فقط تجزئته (hash) هي التي تنتقل:

```bash
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` يعطي رمز تحديث (refresh token)، لذلك لا يحتاج الشخص إلى الموافقة مرة أخرى كل 30 دقيقة.

يسجل الشخص الدخول إلى Anpheros، ويقرأ الطلب بلغة واضحة، ويختار السجل الذي سيشاركه (سجله الخاص، سجل فرد من العائلة يهتم به، أو السجل الذي أنشأه تطبيقك له)، ومدة الوصول، ثم يسمح أو يرفض. يعودون إلى عنوان URI الخاص بإعادة التوجيه لديك:

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

تحقق من أن `state` هي القيمة التي أرسلتها قبل استخدام الرمز.

## الخطوة 4: تبادل الرمز للحصول على الرموز المميزة

```bash
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
```

```json
{"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_token` هو رمز OpenID Connect الذي تسمي فيه المطالبة `fhirUser` مورد المريض.
- يعمل الرمز مرة واحدة فقط، ومع `code_verifier` المطابق فقط.

## الخطوة 5: استدعاء الـ API ضمن النطاقات

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

تأتي نتائج المختبر كالمعتاد. اطلب شيئًا خارج النطاق الممنوح، مثل الأدوية:

```bash
curl "https://platform.anpheros.com/fhir/R4/MedicationStatement?patient=$PATIENT" -H "Authorization: Bearer $ACCESS_TOKEN"
```

```json
{"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`) و [واجهة برمجة تطبيقات السياق](https://developers.anpheros.com/ar/guides/llm-healthcare-data) نفس النطاقات.

## الخطوة 6: التحديث

تنتهي صلاحية رموز الوصول بعد 30 دقيقة. تنتهي صلاحية رموز التحديث بعد 30 يومًا وتتغير مع كل استخدام:

```bash
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 في أي وقت، ويمكنك إلغاءه بنفسك، على سبيل المثال عندما ينفصلون في تطبيقك:

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

منذ ذلك الحين، كل استدعاء بهذا المنح يجيب `401`. تعامل مع ذلك عن طريق إظهار للشخص أن الاتصال قد انتهى وعرض إعادة الاتصال. اشترك في `consent.revoked` [خطاف الويب](https://developers.anpheros.com/ar/guides/webhooks) لمعرفة ذلك دون انتظار استدعاء فاشل.

## باستخدام حزم التطوير (SDKs)

تقوم حزم التطوير [TypeScript و Dart](https://developers.anpheros.com/ar/guides/sdks) بتنفيذ الخطوات من 3 إلى 6 نيابة عنك: `OAuthFlow.authorizeUrl` باستخدام زوج PKCE تم إنشاؤه، `exchange` عند الاستدعاء، وتحديث تلقائي مع التدوير. أمثلة كاملة: [كيفية بناء تطبيق رعاية صحية بالذكاء الاصطناعي مع واجهة خلفية FHIR](https://developers.anpheros.com/ar/guides/build-ai-healthcare-app) (TypeScript) و [كيفية بناء تطبيق رعاية صحية باستخدام Flutter](https://developers.anpheros.com/guides/healthcare-app-flutter) (Dart).

## ما يطبقه Anpheros

| جزء من SMART | في Anpheros |
|---|---|
| الاكتشاف | `/.well-known/smart-configuration` على أساس FHIR، مع نقاط النهاية والنطاقات وطرق PKCE المدعومة |
| التشغيل | تشغيل مستقل (يبدأ التطبيق، ثم يطلب الوصول)؛ لا يتم تقديم تشغيل EHR من داخل نظام سريري |
| التفويض | OAuth 2.1 مع PKCE مطلوب، تدفق رمز التفويض |
| النطاقات | نطاقات المرضى SMART v2، `patient/<Resource>.<cruds>` مع عوامل تصفية الفئات، بالإضافة إلى `openid` و `fhirUser` |
| الهوية | OpenID Connect `id_token` يسمي المريض كمورد FHIR |
| الموافقة | شاشة موافقة مستضافة بلغة المريض، مع تحديد المدة بواسطة المريض، منعكسة كـ FHIR `Consent` |
| الرموز | رموز وصول لمدة 30 دقيقة، رموز تحديث دوارة لمدة 30 يومًا مرتبطة بالموافقة، الإلغاء |
| المطابقة | بيان القدرة يعلن عن خدمة أمان SMART؛ مجموعة "التشغيل المستقل" من مجموعة اختبار تشغيل تطبيق SMART Inferno STU2 تجتاز 22 من أصل 22 اختبارًا (تشغيل في 28 سبتمبر 2026)؛ لم يتم تشغيل مجموعات وأدوات اختبار Inferno الأخرى |

الكتابة تعمل بنفس الطريقة: اكتب النطاقات (`patient/Observation.c`، `.u`، `.d`) تسمح لتطبيقك بإنشاء أو تحديث أو حذف داخل السجل. كل ما يتم كتابته يحمل تطبيقك كالمؤلف، وإعادة المحاولة باستخدام مفتاح عدم التكرار لا تكرر القياس أبدًا، وعمليات الحذف ناعمة وتحتفظ بالتاريخ ([Medical data API](https://developers.anpheros.com/ar/guides/medical-data-api)).

## ما هو غير متوفر حاليًا

- تشغيل السجل الصحي الإلكتروني (EHR) (التطبيق الذي يتم فتحه من داخل نظام المستشفى مع سياق تشغيل).
- `system/` نطاق (scopes) لخدمات الواجهة الخلفية (backend services)؛ تستخدم المؤسسات مفاتيح الواجهة البرمجية (API keys) بدلاً من ذلك.
- تصدير البيانات المجمعة (Bulk Data export) (`$export`)؛ تصدير بيانات مريض واحد (`$everything`) متاح.

تم إدراج هذه الميزات مع الباقي في [الإصدارات والإيقاف](https://developers.anpheros.com/ar/guides/versioning)، وبيان القدرة (capability statement) هو دائمًا المصدر الموثوق.

## أسئلة متكررة

### ما هو SMART on FHIR؟
هو معيار مفتوح، مبني على OAuth 2.0/2.1 و OpenID Connect، يحدد كيفية طلب التطبيق الوصول إلى سجل FHIR، وما هي النطاقات (scopes) التي تصف هذا الوصول، وكيف يعلن الخادم عن نقاط النهاية الخاصة به. يمكن لأي مكتبة عميل تدعم SMART استخدام أي خادم يدعم SMART.

### هل أحتاج إلى PKCE؟
نعم. يتطلب Anpheros استخدام PKCE مع `S256` لكل تدفق رمز التفويض، لكل من العملاء العامين والعملاء السريين على حد سواء. هذا يمنع استخدام رمز التفويض الذي تم اعتراضه من قبل أي شخص آخر.

### ماذا يحدث إذا رفض الشخص؟
يعودون إلى عنوان URI لإعادة التوجيه الخاص بك مع `error=access_denied` و `state` الخاص بك، وبدون رمز. اشرح ما تحتاجه الميزة ودعهم يحاولون مرة أخرى؛ الاستدعاءات خارج نطاق المنحة تجيب دائمًا `403`.

### هل يمكن للوالد منح الموافقة لطفل؟
نعم. في شاشة الموافقة، يمكن للشخص اختيار سجل يهتم به، مثل سجل طفل، إذا كان مرتبطًا بحسابه. تنطبق المنحة على هذا السجل فقط.

## ذات الصلة

- [المصادقة و OAuth](https://developers.anpheros.com/ar/guides/authentication): مفاتيح API، الرموز المميزة وفترات صلاحيتها بالتفصيل
- [واجهة برمجة تطبيقات الرعاية الصحية بموافقة المريض](https://developers.anpheros.com/ar/guides/healthcare-api-patient-consent): كيف تغير الموافقة تصميم تطبيقك
- [نموذج الموافقة والوصول](https://developers.anpheros.com/ar/guides/consent)
- [منصة FHIR](https://developers.anpheros.com/ar/guides/fhir)
- [بناء تطبيق رعاية صحية](https://developers.anpheros.com/ar/guides/build-a-healthcare-app)
