اطلاعیه مهم درباره سرویس Auth Push

این سرویس آزمایشی است و فقط برای اکانت‌های دارای اشتراک PRO قابل استفاده است. اگر سرویس عادی پوشفا را به شکل فعال دارید، نیازی به مطالعه این مستندات ندارید. همچنین چنانچه نیاز به ارسال پیام به کاربران سازمانتان دارید، مستندات این لینک را مطالعه کنید.

آزمایشی · وب‌سرویس‌ها

وب‌سرویس‌های سرویس Auth Push آزمایشی

راهنمای درخواست‌های سروری سرویس Auth Push؛ ثبت دستگاه مورد اعتماد، ساخت درخواست ورود، بررسی نتیجه و حذف اعتماد دستگاه.

POST
https://pushfa.com/api/webservices/auth-push/*
دانلود کالکشن Postman

پیش از ارسال درخواست چه نکاتی را رعایت کنید؟

همه درخواست‌های این صفحه باید از سرور سایت شما فرستاده شوند. هر درخواست به کلید عمومی و کلید خصوصی همان سرویس نیاز دارد. شناسه واقعی کاربر را از دیتابیس یا نشست معتبر خودتان بردارید و هیچ‌وقت اجازه ندهید مرورگر آزادانه آن را تعیین کند.

این قابلیت هنوز آزمایشی است. کلید خصوصی را فقط در Secret Manager یا متغیر محیطی سرور نگه دارید و روش ورود پیامکی فعلی را به‌عنوان مسیر جایگزین حفظ کنید.
مسیربه زبان ساده چه کاری می‌کند؟
POST /auth-push/bind دستگاه فعلی را به‌عنوان دستگاه مورد اعتماد یک کاربر ثبت می‌کند.
POST /auth-push/unbind اعتماد دستگاه را برمی‌دارد و درخواست‌های باز آن را باطل می‌کند.
POST /auth-push/challenges یک درخواست کوتاه‌مدت برای تأیید مستقیم یا کد شش‌رقمی می‌سازد.
POST /auth-push/grants/consume مجوز یک‌بارمصرف را بررسی می‌کند تا سرور بتواند کاربر را وارد کند.

ترتیب معمول فراخوانی وب‌سرویس‌ها

ثبت دستگاه مورد اعتماد

بعد از ورود معتبر، سرور bind را با expires_at برابر پایان واقعی Session یا Access Token فراخوانی می‌کند.

ساخت درخواست ورود

در ورود بعدی، سرور با challenges یک درخواست کوتاه‌مدت می‌سازد.

انتظار برای پاسخ کاربر

مرورگر با SDK منتظر تأیید یا ورود کد می‌ماند.

بررسی نتیجه نهایی

سرور Grant را با grants/consume بررسی می‌کند و سپس نشست ورود را می‌سازد.

انقضا یا حذف اعتماد

در پایان expires_at اعتماد خودکار منقضی می‌شود؛ در خروج، revoke یا حذف زودتر دستگاه، سرور unbind را فراخوانی می‌کند.

۲. ثبت دستگاه به‌عنوان دستگاه مورد اعتماد

POST
https://pushfa.com/api/webservices/auth-push/bind
این درخواست را فقط بعد از ورود معتبر بفرستید و expires_at را از پایان واقعی Session، JWT یا Access Token بسازید. پس از این زمان دستگاه خودکار از سرویس Auth Push خارج و درخواست‌های باز آن باطل می‌شوند. در logout یا revoke زودتر از موعد همچنان unbind را فراخوانی کنید. حذف expires_at فقط برای سازگاری قبلی است و بایند را بدون انقضا می‌سازد.
فیلدتوضیحالزام
api_public_key کلید عمومی سرویس بله
api_private_key کلید خصوصی سرویس؛ فقط سرور بله
subscriber_id شناسه پایدار دستگاهی که کاربر روی آن احراز هویت شده است بله
auth_identity شناسه داخلی و پایدار کاربر در سیستم شما؛ مانند user UUID بله
expires_at زمان پایان اعتبار بایند به فرمت ISO 8601؛ باید برابر پایان Session یا Access Token باشد خیر؛ بدون آن بایند نامحدود است
curl -X POST https://pushfa.com/api/webservices/auth-push/bind \
  -H "Content-Type: application/json" \
  -d '{
    "api_public_key": "YOUR_PUBLIC_KEY",
    "api_private_key": "YOUR_PRIVATE_KEY",
    "subscriber_id": "DEVICE_SUBSCRIBER_UUID",
    "auth_identity": "YOUR_USER_UUID",
    "expires_at": "2026-09-07T12:30:00Z"
  }'

نمونه اتصال دستگاه در Laravel

در این نمونه، UUID کاربر از نشست احراز هویت‌شده گرفته می‌شود و expires_at براساس عمر داینامیک همان نشست ساخته می‌شود. اگر JWT یا Access Token دارید، دقیقاً claim مربوط به exp یا expires_at همان توکن را بفرستید.

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

Route::post('/account/trusted-device', function (Request $request) {
    $data = $request->validate(['subscriber_id' => ['required', 'uuid']]);
    // برای JWT/Access Token، زمان exp واقعی همان توکن را جایگزین کنید.
    $bindingExpiresAt = now()->addMinutes((int) config('session.lifetime'));

    Http::asJson()->post('https://pushfa.com/api/webservices/auth-push/bind', [
        'api_public_key' => config('services.pushfa.public_key'),
        'api_private_key' => config('services.pushfa.private_key'),
        'subscriber_id' => $data['subscriber_id'],
        'auth_identity' => $request->user()->uuid,
        'expires_at' => $bindingExpiresAt->toISOString(),
    ])->throw();

    return response()->json([
        'trusted' => true,
        'expires_at' => $bindingExpiresAt->toISOString(),
    ]);
})->middleware('auth');

۳. ساخت درخواست کوتاه‌مدت ورود

POST
https://pushfa.com/api/webservices/auth-push/challenges

سرور سایت شناسه کاربر و شناسه دستگاهی را که منتظر ورود است برای پوشفا می‌فرستد. پوشفا به همان دستگاه اعلان نمی‌فرستد و حداکثر پنج دستگاه فعال دیگر کاربر را انتخاب می‌کند. روش درخواست می‌تواند تأیید مستقیم یا کد شش‌رقاست.

پاسخ شامل شناسه درخواست، توکن کوتاه‌مدت Client، زمان پایان و تعداد دستگاه‌های مقصد است. اگر دستگاه مناسبی پیدا نشود، fallback_required=true برمی‌شود تا سرور بتواند ورود با پیامک را آغاز کند.
فیلدتوضیحالزام
api_public_key / api_private_key کلیدهای سرویس بله
auth_identity همان شناسه داخلی استفاده‌شده هنگام bind بله
requester_subscriber_id شناسه ثابت مخاطب (Subscriber ID) دستگاهی که منتظر ورود است بله
mode approval برای تأیید روی دستگاه دیگر یا otp برای نمایش کد روی دستگاه دیگر خیر؛ پیش‌فرض approval
expires_in زمان اعتبار بین ۶۰ تا ۳۰۰ ثانیه خیر؛ پیش‌فرض ۱۲۰
reference شناسه داخلی درخواست در سمت سرور شما خیر
context[ip/device/location] اطلاعاتی که در صفحه تأیید به کاربر نمایش داده می‌شود خیر
curl -X POST https://pushfa.com/api/webservices/auth-push/challenges \
  -H "Content-Type: application/json" \
  -d '{
    "api_public_key": "YOUR_PUBLIC_KEY",
    "api_private_key": "YOUR_PRIVATE_KEY",
    "auth_identity": "YOUR_USER_UUID",
    "requester_subscriber_id": "REQUESTER_SUBSCRIBER_UUID",
    "mode": "approval",
    "expires_in": 120
  }'

نمونه Endpoint شروع ورود در سمت سرور

سرور ابتدا کاربر را با شماره موبایل یا شناسه ورود پیدا می‌کند، auth_identity واقعی را از دیتابیس خودش برمی‌دارد و Challenge را می‌سازد. api_private_key هرگز در پاسخ مرورگر قرار نمی‌گیرد.

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

Route::post('/auth/push/start', function (Request $request) {
    $data = $request->validate([
        'username' => ['required', 'string'],
        'subscriber_id' => ['required', 'uuid'],
        'mode' => ['nullable', 'in:approval,otp'],
    ]);

    $user = User::where('username', $data['username'])->firstOrFail();
    $response = Http::asJson()->post(
        'https://pushfa.com/api/webservices/auth-push/challenges',
        [
            'api_public_key' => config('services.pushfa.public_key'),
            'api_private_key' => config('services.pushfa.private_key'),
            'auth_identity' => $user->uuid,
            'requester_subscriber_id' => $data['subscriber_id'],
            'mode' => $data['mode'] ?? 'approval',
            'expires_in' => 120,
            'reference' => (string) $user->uuid,
            'context' => [
                'ip' => $request->ip(),
                'device' => $request->userAgent(),
            ],
        ]
    );

    if ($response->status() === 422) {
        return response()->json(['fallback_required' => true], 422);
    }

    return response()->json($response->throw()->json('data'));
})->middleware('throttle:5,1');

۶. بررسی مجوز یک‌بارمصرف و ورود کاربر

POST
https://pushfa.com/api/webservices/auth-push/grants/consume

بعد از تأیید، SDK یک Grant کوتاه‌عمر برمی‌گرداند. مرورگر آن را برای سرور سایت می‌فرستد. سرور با کلید خصوصی اعتبار Grant و کاربر مربوط به آن را بررسی می‌کند و فقط پس از دریافت verified=true نشست ورود را می‌سازد.

Grant فقط یک بار، پیش از پایان زمان و برای همان کاربر قابل استفاده است. Cookie یا Access Token را تنها پس از verified=true صادر کنید.
فیلدتوضیحالزام
api_public_key / api_private_key کلیدهای سرویس بله
challenge_id شناسه Challenge بله
grant Grant دریافتی فقط پس از تأیید بله
auth_identity شناسه داخلی کاربری که قرار است وارد شود بله
curl -X POST https://pushfa.com/api/webservices/auth-push/grants/consume \
  -H "Content-Type: application/json" \
  -d '{
    "api_public_key": "YOUR_PUBLIC_KEY",
    "api_private_key": "YOUR_PRIVATE_KEY",
    "challenge_id": "CHALLENGE_UUID",
    "grant": "ONE_TIME_GRANT",
    "auth_identity": "YOUR_USER_UUID"
  }'

نمونه تکمیل Login در سمت سرور

Route::post('/auth/push/complete', function (Request $request) {
    $data = $request->validate([
        'challenge_id' => ['required', 'uuid'],
        'grant' => ['required', 'string', 'size:64'],
    ]);

    // نگاشت Challenge به کاربر باید در state امن Backend شما نگهداری شود.
    $user = resolveUserForChallenge($data['challenge_id']);
    $verified = Http::asJson()->post(
        'https://pushfa.com/api/webservices/auth-push/grants/consume',
        [
            'api_public_key' => config('services.pushfa.public_key'),
            'api_private_key' => config('services.pushfa.private_key'),
            'challenge_id' => $data['challenge_id'],
            'grant' => $data['grant'],
            'auth_identity' => $user->uuid,
        ]
    )->throw()->json('data.verified');

    abort_unless($verified === true, 401);
    auth()->login($user);
    $request->session()->regenerate();

    return response()->json(['redirect_to' => '/dashboard']);
});

حذف اعتماد دستگاه

POST
https://pushfa.com/api/webservices/auth-push/unbind

با رسیدن expires_at، پوشفا بایند را خودکار منقضی و درخواست‌ها و Grantهای باز مرتبط را باطل می‌کند. اگر کاربر پیش از آن logout کرد، نشست revoke شد، مالک دستگاه تغییر کرد یا دستگاه حذف شد، سرور باید فوراً unbind را فراخوانی کند.

curl -X POST https://pushfa.com/api/webservices/auth-push/unbind \
  -H "Content-Type: application/json" \
  -d '{
    "api_public_key": "YOUR_PUBLIC_KEY",
    "api_private_key": "YOUR_PRIVATE_KEY",
    "subscriber_id": "DEVICE_SUBSCRIBER_UUID"
  }'

فهرست بررسی امنیتی محیط عملیاتی

کنترلالزام
کلید خصوصی فقط در Secret Manager یا متغیر محیطی سرور نگهداری شود.
مالکیت هویت auth_identity فقط از دیتابیس و نشست معتبر سرور استخراج شود، نه از ورودی مرورگر.
نگاشت Challenge Challenge را در سمت سرور به همان تلاش ورود و همان کاربر متصل کنید.
Session fixation پس از مصرف Grant، شناسه Session را regenerate کنید.
Rate limit روی مسیرهای وب‌سرویس داخلی start و complete علاوه بر محدودیت پوشفا، محدودیت IP و حساب اعمال کنید.
نمایش درخواست IP، نوع دستگاه و موقعیت تقریبی را برای تشخیص درخواست ناشناس به کاربر نشان دهید.
Fallback fallback پیامک را فقط پس از لغو Challenge قبلی آغاز کنید.
انقضا، Logout و revoke expires_at را با پایان واقعی توکن همگام کنید و برای خروج یا revoke زودتر از موعد unbind را فراموش نکنید.
ثبت رویداد نتیجه نهایی را بدون ذخیره OTP، client_token، Grant یا api_private_key در audit log ثبت کنید.

خطاها و رفتار مورد انتظار سرور

حالتتفسیراقدام
422 + fallback_required دستگاه واجد شرایط وجود ندارد یا ارسال امن ممکن نیست. Challenge را خطای سیستمی تلقی نکنید و fallback را آغاز کنید.
401/403 کلیدها، مالکیت سرویس یا دسترسی معتبر نیست. درخواست را متوقف و تنظیم Secret/Service را بررسی کنید.
expired/rejected/cancelled Challenge دیگر قابل تکمیل نیست. Grant یا client_token قبلی را استفاده نکنید.
consumed Grant قبلاً یک بار مصرف شده است. Session قبلی را بررسی و از مصرف دوباره جلوگیری کنید.
429 محدودیت نرخ اعمال شده است. Backoff و محدودیت داخلی IP/Account را رعایت کنید.
Ctrl+I