احراز هویت
توکنهای API برای یکپارچهسازیها، نشستهای JWT برای برنامههای کاربرمحور، و مدل مجوزی که هر دو بر اساس آن ارزیابی میشوند.
آخرین بازنگری: 2026-08-23
دو نوع اعتبارنامه
هر دو به یک شکل ارائه میشوند - Authorization: Bearer <value> - و سرور آنها را از روی خودِ مقدار تشخیص میدهد. اینکه کدام را میخواهید بستگی دارد به اینکه چه کسی در حال عمل است.
| توکن API | نشست JWT | |
|---|---|---|
| ظاهر | ct_live_… | یک JWT (eyJ…) |
| بهنمایندگی از | یک یکپارچهسازی | شخصِ واردشده |
| از کجا | تنظیمات ← توکنهای API یا POST /api-tokens | POST /auth/login |
| طول عمر | تا زمان ابطال یا تاریخ انقضا | حدود یک ساعت، سپس تازهسازی |
| مناسب برای | سرور به سرور، cron، ETL | برنامهای که کاربران در آن وارد میشوند |
توکنهای API (پیشنهاد برای یکپارچهسازی)
توکن API به فضای کاری تعلق دارد نه به یک شخص؛ بنابراین با رفتن همکاری که آن را ساخته است، یکپارچهسازی از کار نمیافتد. در برنامه از مسیر تنظیمات ← توکنهای API بسازید، یا از راه API:
curl -sS -X POST https://your-host/api/v1/api-tokens \
-H "Authorization: Bearer <your session token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Storefront sync",
"description": "Pushes orders from the website",
"permissions": ["crm.contacts.read", "crm.contacts.write", "sales.orders.write"],
"expires_at": "2027-01-01T00:00:00"
}'{
"id": 12,
"name": "Storefront sync",
"token": "ct_live_9Xf2…",
"token_prefix": "ct_live_9Xf2",
"permissions": ["crm.contacts.read", "crm.contacts.write", "sales.orders.write"],
"expires_at": "2027-01-01T00:00:00",
"created_at": "2026-08-23T10:12:00"
}دو فیلد تعیین میکنند توکن تا کجا میتواند پیش برود و مستقل از هماند:
- `permissions` - چه کاری مجاز است. باریکترین مجموعهای را بدهید که یکپارچهسازی واقعاً لازم دارد.
GET /permissionsهمهٔ کدهایی را که محصول تعریف میکند فهرست میکند. - `acts_as_user_id` - *دیدپذیری ردیف* را از چه کسی قرض میگیرد. اگر نفرستید، توکن جایگاه کاربر سازنده را به ارث میبرد که پیشفرض امن است؛ برای توکن بیمحدودیت
nullبفرستید. این فیلد هرگز مجوزی اضافه نمیکند - فقط دامنهٔ ردیفهایی را که مجوزهای دادهشده به آنها میرسند تنگتر میکند.
ابطال با POST /api-tokens/{token_id}/revoke انجام میشود و توکن بیدرنگ از کار میافتد. GET /api-tokens/{token_id}/audit نشان میدهد این توکن چه کرده است؛ نخستین جایی که باید سراغش رفت اگر گمان نشت داشتید.
توکنهای نشست
وقتی برنامهٔ شما یک *شخص* را وارد میکند و بهنمایندگی از او عمل میکند از اینها استفاده کنید تا هر اقدام به خودش نسبت داده شود و بر اساس نقش خودش سنجیده شود.
curl -sS -X POST https://your-host/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"tenant_slug": "acme",
"email": "sara@example.com",
"password": "…"
}'{
"access_token": "eyJhbGciOi…",
"refresh_token": "eyJhbGciOi…",
"token_type": "bearer",
"user": { "id": 5, "email": "sara@example.com", "first_name": "Sara", "last_name": "Ahmadi" },
"tenant": { "id": 17, "slug": "acme", "name": "Acme Inc." },
"permissions": ["crm.contacts.read", "crm.contacts.write", "…"]
}tenant_slug اجباری است: یک نشانی ایمیل میتواند در بیش از یک فضای کاری وجود داشته باشد و این نامک است که میگوید به کدامیک وارد میشوید.
توکن دسترسی کوتاهعمر است. وقتی فراخوانیای ۴۰۱ برگرداند، توکن تازهسازی را در POST /auth/refresh مبادله کنید - یعنی refresh token را بهعنوان bearer بفرستید - و یک بار دوباره تلاش کنید. مسیر refresh فقط توکن تازهسازی میپذیرد؛ توکن API نه تازهسازی میشود و نه به آن نیاز دارد.
curl -sS -X POST https://your-host/api/v1/auth/refresh \
-H "Authorization: Bearer <refresh_token>"مجوزها
مجوزها کدهای نقطهداری با ساختار module.resource.action هستند و هر نقطهٔ پایانی محافظتشده دقیقاً کدی را که لازم دارد نام میبرد. «scope» جدا از مجوز وجود ندارد: توکن API زیرمجموعهای از همان کدهایی را دارد که یک نقش دارد.
crm.contacts.read crm.contacts.write crm.contacts.delete
crm.contacts.view_phone crm.deals.read crm.tasks.write
webhooks.read webhooks.write api_tokens.write
events.read finance.invoices.read sales.orders.writeنبودِ یک مجوز، یک ۴۰۳ است که details.required آن میگوید چه چیزی لازم بوده - تا کلاینت بتواند چیزی قابلاقدام لاگ کند نه صرفاً «ممنوع».
{
"error": "forbidden",
"message": "Missing required permissions",
"details": { "required": ["crm.contacts.write"] }
}نگهداری امن توکن
- آن را در یک مدیر راز یا متغیر محیطی نگه دارید - نه در مخزن، نه در ایمیج کانتینر، نه در باندل سمت مرورگر.
- باریکترین مجموعهٔ مجوزی را که کار میکند بدهید و برای هر یکپارچهسازی توکن جدا بسازید تا ابطال یکی بقیه را از کار نیندازد.
- هرجا یکپارچهسازی طول عمر مشخصی دارد،
expires_atرا تنظیم کنید. - چرخش را زمانبندی کنید: اول جایگزین را بسازید، بعد مستقر کنید، بعد قدیمی را باطل کنید - به همین ترتیب تا وقفهای پیش نیاید.
- بهمحض تردید باطل کنید و
GET /api-tokens/{token_id}/auditرا بعد از ابطال بخوانید، نه قبل از آن.