احراز دسترسی OAuth
چگونه هما متا پلتفرم یک درخواست احراز دسترسی را آغاز میکند، آن را در برابر CSRF محافظت میکند، کد احراز دسترسی را روی سرور مبادله میکند و دسترسی را لغو میکند.
نشانی بازگشت
نشانی بازگشت باید در داشبورد اپلیکیشنهای متا ثبت شده باشد و موبهمو با مقدار ارسالی در درخواست احراز دسترسی مطابقت داشته باشد. هما از یک هدف بازگشت واحد در محیط تولید استفاده میکند.
| محیط | نشانی بازگشت |
|---|---|
| تولید | https://meta.homacrm.com/authorized |
| توسعه | بهصورت جداگانه در اپلیکیشن توسعه ثبت میشود |
- در محیط تولید همیشه از HTTPS استفاده کنید.
- به نشانی بازگشت ثبتشده پارامتر پرسوجو اضافه نکنید.
- اسلش پایانی را معنادار در نظر بگیرید؛ دقیقاً همان شکلی را ثبت کنید که ارسال میکنید.
- میزبانهای محیط توسعه را فقط در اپلیکیشن توسعه ثبت کنید، هرگز در اپلیکیشن تولید.
پارامتر state و محافظت در برابر CSRF
پارامتر state بازگشت را به همان نشست مرورگری که فرایند را آغاز کرده است متصل میکند. بدون آن، یک مهاجم میتواند کد احراز دسترسی خود را به کاربری واردشده تحویل دهد و حسابی را متصل کند که کاربر هرگز قصد اتصال آن را نداشته است.
- پیش از هدایت کاربر، یک مقدار تصادفی رمزنگاریشده تولید کنید.
- آن را در کوکی HttpOnly، Secure و SameSite=Lax با عمر کوتاه ذخیره کنید.
- همان مقدار را بهعنوان پارامتر پرسوجوی state ارسال کنید.
- در بازگشت، مقدار پرسوجو را با کوکی از طریق مقایسهٔ زمانثابت بسنجید.
- کوکی را بیدرنگ پس از مقایسه پاک کنید، چه موفق باشد و چه ناموفق.
- اگر مقادیر متفاوت بودند یا کوکی وجود نداشت، بازگشت را رد کنید.
// مسیر صرفاً سمت سرور.
const state = crypto.randomUUID()
const url = new URL(process.env.META_AUTHORIZATION_URL!)
url.searchParams.set('client_id', process.env.META_APP_ID!)
url.searchParams.set('redirect_uri', process.env.META_REDIRECT_URI!)
url.searchParams.set('response_type', 'code')
url.searchParams.set('state', state)
const response = NextResponse.redirect(url)
response.cookies.set('meta_oauth_state', state, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
maxAge: 600,
})
return responseمدیریت کد احراز دسترسی و مبادلهٔ توکن
کد احراز دسترسی یکبارمصرف و کوتاهعمر است. آن را بیدرنگ و سمت سرور مبادله کنید، سپس دور بیندازید. این کد هرگز نباید در گزارشها ثبت، ذخیره یا به مرورگر بازگردانده شود.
const returnedState = searchParams.get('state')
const code = searchParams.get('code')
const expectedState = cookies().get('meta_oauth_state')?.value
// ابتدا همیشه کوکی یکبارمصرف state را پاک کنید.
cookies().delete('meta_oauth_state')
if (!code || !returnedState || !expectedState) {
return redirect('/auth-error')
}
if (!timingSafeEqual(returnedState, expectedState)) {
return redirect('/auth-error')
}
// سروربهسرور. کلید محرمانه هرگز از این فرایند بیرون نمیرود.
const token = await exchangeCodeForToken({
code,
appId: process.env.META_APP_ID!,
appSecret: process.env.META_APP_SECRET!,
redirectUri: process.env.META_REDIRECT_URI!,
})
await storeEncryptedToken({ tenantId, token })
return redirect('/authorized')ذخیرهسازی توکن
توکنها در ذخیرهسازی رمزنگاریشده و کلیدگذاریشده بر اساس مستأجر نوشته میشوند و هرگز به کلاینت بازگردانده نمیشوند. چرخهٔ کامل عمر را در صفحهٔ توکنها ببینید.
- رمزنگاری در حالت سکون با کلیدی که بیرون از پایگاه دادهٔ اپلیکیشن نگهداری میشود.
- هر خواندن را با شناسهٔ مستأجر محدود کنید تا یک مشتری نتواند به توکن مشتری دیگر دسترسی یابد.
- هرگز توکن را در نشانی، رشتهٔ پرسوجو، خط گزارش یا رویداد تحلیلی قرار ندهید.
- هرگز توکن را به مرورگر ارسال نکنید، حتی روی HTTPS.
مدیریت خطا
هر مسیر خطا به /auth-error با پیامی عمومی ختم میشود. آن صفحه علتهای احتمالی را بدون افشای پاسخهای ارائهدهنده توضیح میدهد.
- انصراف کاربر
- متا بهجای کد، یک پارامتر خطا برمیگرداند. امکان تلاش مجدد را فراهم کنید؛ این وضعیت نقص نیست.
- state نامعتبر یا غایب
- بازگشت را رد کنید و فرایند را از ابتدا آغاز کنید. مبادله را انجام ندهید.
- عدم تطابق نشانی بازگشت
- خطای پیکربندی است. نشانی ثبتشده در داشبورد اپلیکیشن را با META_REDIRECT_URI مقایسه کنید.
- مجوز غایب
- کاربر یک دامنهٔ دسترسی را نپذیرفته است. بهجای تکرار نام خام دامنه، توضیح دهید کدام قابلیت در دسترس نیست.
لغو دسترسی
دسترسی میتواند از هر دو سو پایان یابد. هر دو مسیر باید به یک پاکسازی یکسان برسند.
- کاربر اتصال را از داخل هما CRM قطع میکند.
- کاربر هما متا پلتفرم را از تنظیمات حساب متای خود حذف میکند که فراخوان لغو دسترسی را فعال میکند.
- یک توکن لغو یا منقضی میشود و قابل تازهسازی نیست.
- توکن ذخیرهشده را حذف و اتصال را غیرفعال علامتگذاری کنید.
- همهٔ فراخوانیهای دورهای و تماسهای خروجی مربوط به آن دارایی را متوقف کنید.
- لغو دسترسی را با عامل و مهر زمانی در گزارش حسابرسی ثبت کنید.
- در موارد مربوط، فرایند حذف داده را برای دادههای وابسته اجرا کنید.
هرگز افشا نکردن کلیدهای محرمانه در کد مرورگر
- مقدار META_APP_SECRET تنها در ماژولها و مسیرهای صرفاً سمت سرور خوانده میشود.
- هیچ کلید محرمانهای پیشوند NEXT_PUBLIC_ ندارد.
- مؤلفهٔ کلاینت در /connect تنها یک تأیید رضایت ارسال میکند و نه چیز دیگر؛ هیچ هویتی از اپلیکیشن در اختیار ندارد.
- کد کلاینت هرگز توکن دسترسی، کد احراز دسترسی یا مقدار state دریافت نمیکند.
- اگر کلید محرمانهٔ اپلیکیشن در گزارشی چاپ شد، در کنترل نسخه ثبت شد یا در یک تیکت پشتیبانی درج شد، آن را تغییر دهید.