37 lines
3.7 KiB
Markdown
37 lines
3.7 KiB
Markdown
# مصادقة SportPath — API v1
|
|
|
|
هذه الواجهات تأسيس أولي لمصادقة رقم الهاتف. لا تشغّل إرسال OTP قبل إعداد مزود حقيقي ومراجعة عقده على بيئة sandbox. لا يخرج الرمز أو المفاتيح في response أو logs.
|
|
|
|
## إعداد الخادم
|
|
|
|
ضع القيم في ملف البيئة الخاص خارج مجلد `public/`:
|
|
|
|
```dotenv
|
|
JWT_SIGNING_KEY=<random secret, at least 32 bytes>
|
|
JWT_ACCESS_TTL_SECONDS=900
|
|
JWT_REFRESH_TTL_DAYS=30
|
|
OTP_PROVIDER=generic_json
|
|
OTP_API_URL=https://provider.example/api/send
|
|
OTP_API_KEY=<server-only token>
|
|
OTP_SENDER_ID=<approved sender>
|
|
OTP_MESSAGE_TEMPLATE=رمز التحقق الخاص بك هو {code}
|
|
OTP_ENABLED=true
|
|
OTP_HASH_KEY=<independent random secret, at least 32 bytes>
|
|
```
|
|
|
|
المحول الحالي يرسل JSON بالشكل `{"to":"+...","sender":"...","message":"..."}` مع `Authorization: Bearer ...`، ويعد أي HTTP 2xx نجاحًا. هذا عقد عام مؤقت وليس افتراضًا عن أي مزود؛ عدّل `ConfiguredHttpOtpProvider` ليتوافق مع توثيق المزود الفعلي قبل تفعيل الإنتاج. يرفض endpoint العناوين غير HTTPS. في حال غياب الإعداد يبقى الطلب مغلقًا ويرجع 503.
|
|
|
|
## المسارات
|
|
|
|
- `POST /api/v1/auth/request-otp.php`: JSON `{ "phone_e164": "+962…", "purpose": "register|login", "device_uuid": "UUID" }`. يرد `challenge_id` ومدة الصلاحية. حد الإرسال الحالي 5 لكل رقم/ساعة، 20 لكل IP/ساعة، و10 لكل device/ساعة؛ المحاولات لكل تحدٍ 5 خلال 5 دقائق.
|
|
- `POST /api/v1/auth/verify-otp.php`: JSON `{ "challenge_id": "UUID", "code": "123456", "display_name": "…", "device_uuid": "UUID", "platform": "ios|android|web" }`. يستهلك التحدي مرة واحدة ويصدر JWT وrefresh token عشوائيًا. يجب حفظ refresh token في مخزن آمن على الجهاز، وعدم تسجيل أي token.
|
|
- `POST /api/v1/auth/refresh.php`: JSON `{ "refresh_token": "…" }`. تدوير الرمز يصدر refresh جديدًا؛ إعادة استخدام رمز سبق تدويره تبطل عائلة الجلسة.
|
|
- `POST /api/v1/auth/logout.php`: يتطلب `Authorization: Bearer <access-token>` ويبطل الجلسة الحالية.
|
|
- `/api/v1/admin/settings.php`: يتطلب bearer token ودور `owner` أو `content_manager`؛ GET للقراءة وPATCH للتعديل مع audit trail.
|
|
|
|
كل Access Token قصير العمر ويرتبط بجلسة حية في MySQL. الدور وحالة الحساب يعاد التحقق منهما من قاعدة البيانات لكل طلب محمي. لا تُقبل معرفات عتادية ثابتة؛ `device_uuid` معرّف تثبيت عشوائي. ترقية أول مالك تتم يدويًا على قاعدة الخادم بعد التحقق من رقم الهاتف، ولا توجد واجهة bootstrap عامة لمنح دور owner.
|
|
|
|
## ما لم يكتمل بعد
|
|
|
|
هذا API غير مربوط بعد بتطبيق Flutter، ونقاط التتبع القديمة ما زالت تستخدم HMAC الانتقالي. قبل الإنتاج يجب نقل التطبيق إلى OTP/refresh الآمن، ثم إيقاف بيانات HMAC القديمة أو حصرها بفترة انتقال معلومة. لم يُختبر اتصال MySQL الفعلي أو إرسال SMS؛ فحوص PHP المتاحة حتى الآن ساكنة فقط. نفّذ migration `001_phone_auth_and_sessions.sql` على قاعدة staging احتياطية أولًا، وتحقق من rate limits والتدوير والإبطال مع مزود OTP في sandbox.
|