🕸 Articles – Telegram
🕸 Articles
2.23K subscribers
43 photos
3 videos
18 files
12 links
Web Security Researcher, Bug Hunter
369
Download Telegram
یه مفهوم داریم به اسم Grant Types بیایید ببینیم این چیه؟

این کلمه Grant Type یعنی روشی که کلاینت توکن رو می‌گیره. توی OAuth 2.0 چند نوع مختلف داریم:

1️⃣ Authorization Code (مهم‌ترین و امن‌ترین روش)

بیشتر برای وب‌سایت‌ها و اپ‌های سمت سرور استفاده میشه.
💡 توی این روش، کاربر اول توی سرور احراز هویت لاگین می‌کنه و بعد به کلاینت یه کد موقت (Authorization Code) داده میشه. بعدش کلاینت اون کد رو به سرور احراز هویت می‌فرسته و یه Access Token می‌گیره.
امن‌ترین روشه، چون پسورد هیچ وقت به کلاینت داده نمیشه.

2️⃣ Implicit Grant (حذف شده!)


برای اپ‌های فرانت‌اند استفاده می‌شد ولی به خاطر مشکلات امنیتی دیگه پیشنهاد نمیشه.

3️⃣ Client Credentials (بدون کاربر، فقط بین سرورها)


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

4️⃣ Password Grant (بدترین روش، دیگه استفاده نمیشه)


این روش مستقیم یوزرنیم و پسورد رو از کاربر می‌گیره و توکن میده. خیلی خطرناکه و دیگه توصیه نمیشه.
1
1
🔄 فلوهای OAuth 2.0 چطوری کار می‌کنه؟

حالا بیایم دقیق‌تر و مرحله‌به‌مرحله بررسی کنیم که وقتی یه کاربر روی دکمه "Login with Facebook" کلیک می‌کنه، چه اتفاقی می‌افته.

ورود با فیسبوک (Authorization Code Flow)
فرض کنید یه سایت داره از OAuth 2.0 برای ورود با فیسبوک استفاده می‌کنه.

مرحله 1: کلیک روی دکمه "Login with Facebook"

کاربر روی دکمه کلیک می‌کنه، و سایت باید کاربر رو بفرسته به سرور احراز هویت فیسبوک.
درخواست ریدایرکت به این URL میره:

GET https://www.facebook.com/v12.0/dialog/oauth
?client_id=123456789
&redirect_uri=https://yourwebsite.com/callback
&response_type=code
&scope=email,public_profile
&state=randomstring123


توضیح پارامترها:

client_id :
آی‌دی کلاینت که فیسبوک به سایت ما داده.

redirect_uri :
بعد از احراز هویت، کاربر رو به این URL برمی‌گردونه.

response_type=code

چون می‌خوایم Authorization Code بگیریم.

scope=email,public_profile :
داریم می‌گیم که می‌خوایم به ایمیل و پروفایل عمومی کاربر دسترسی داشته باشیم.

state=randomstring123:
یه مقدار تصادفی که از CSRF جلوگیری کنه.


اتفاقی که اینجا میفته:
🔹 کاربر به صفحه لاگین فیسبوک هدایت میشه.
🔹 فیسبوک از کاربر می‌پرسه که آیا اجازه میده این سایت به اطلاعاتش دسترسی داشته باشه یا نه؟
1
مرحله 2: تایید کاربر در فیسبوک
🔹 کاربر توی فیسبوک لاگین می‌کنه و روی دکمه "Allow" کلیک می‌کنه.
🔹 فیسبوک حالا کاربر رو برمی‌گردونه به سایت ما و یه Authorization Code میده.

GET https://yourwebsite.com/callback
?code=A1B2C3D4
&state=randomstring123


توضیح:

code=A1B2C3D4 :

یه کد موقت که فقط چند دقیقه اعتبار داره.

state=randomstring123:

اینو چک می‌کنیم که همون مقداریه که قبلاً فرستادیم، تا حمله CSRF اتفاق نیفته.
1
***این مرحله توسط کاربر دیده نمیشه***

مرحله 3: تبدیل Authorization Code به Access Token

حالا سایت ما باید این Authorization Code رو به یه Access Token تبدیل کنه.

🔹 سایت یه درخواست POST می‌فرسته به سرور فیسبوک:
POST https://graph.facebook.com/v12.0/oauth/access_token
Content-Type: application/x-www-form-urlencoded

client_id=123456789
&client_secret=SECRET123
&redirect_uri=https://yourwebsite.com/callback
&code=A1B2C3D4
&grant_type=authorization_code


توضیح:

client_id :

آی‌دی کلاینت که فیسبوک داده.

client_secret :
یه مقدار مخفی که فقط سایت ما داره (برای احراز هویت).

redirect_uri :
باید همون چیزی باشه که توی مرحله اول فرستادیم.


code=A1B2C3D4 :
همون کد موقتی که فیسبوک داده بود.

grant_type=authorization_code :
می‌گیم که می‌خوایم Authorization Code رو به Access Token تبدیل کنیم.



پاسخ فیسبوک:

{
"access_token": "EAAJ3gZB4ZC9wBABZC...",
"token_type": "bearer",
"expires_in": 5184000
}


چی گرفتیم؟

access_token:

این توکن رو داریم و می‌تونیم ازش برای گرفتن اطلاعات کاربر استفاده کنیم!

token_type :
همیشه bearer هست.

expires_in :
زمان اعتبار توکن (معمولاً چند ساعت یا روز).
1
مرحله 4: استفاده از Access Token برای گرفتن اطلاعات کاربر

حالا سایت ما می‌تونه از این Access Token استفاده کنه و اطلاعات کاربر رو از فیسبوک بگیره.

🔹 درخواست به API فیسبوک:

GET https://graph.facebook.com/me
?fields=id,name,email
&access_token=EAAJ3gZB4ZC9wBABZC...


پاسخ فیسبوک:
{
"id": "123456789",
"name": "zarvan",
"email": "zarvan@example.com"
}


حالا سایت ما اطلاعات کاربر رو داره و می‌تونه اونو لاگین کنه!

جمع‌بندی مراحل

1️⃣ کاربر روی "Login with Facebook" کلیک می‌کنه.
2️⃣ سایت کاربر رو می‌فرسته به فیسبوک برای لاگین و اجازه دادن.
3️⃣ فیسبوک بعد از تایید، Authorization Code رو به سایت ما میده.
4️⃣ سایت ما اون کد رو به Access Token تبدیل می‌کنه.
5️⃣ سایت با Access Token به API فیسبوک درخواست میده و اطلاعات کاربر رو می‌گیره.
6️⃣ حالا سایت می‌تونه کاربر رو احراز هویت کنه و داخل سیستم خودش لاگین کنه.

با این روش، سایت بدون اینکه پسورد کاربر رو بگیره، از طریق فیسبوک لاگین انجام میده! 🚀
1
انواع توکن‌ها در OAuth

1️⃣ Access Token (توکن دسترسی)


🔹 یه رشته‌ی یونیک که کلاینت ازش برای درخواست به API استفاده می‌کنه.
🔹 عمرش محدوده (چند دقیقه یا ساعت) و بعدش منقضی میشه.

2️⃣ Refresh Token (توکن تمدید)


🔹 وقتی Access Token منقضی بشه، کلاینت از Refresh Token استفاده می‌کنه تا یه توکن جدید بگیره، بدون اینکه کاربر دوباره لاگین کنه!
🔹 عمر طولانی داره (مثلاً چند روز یا هفته).
1
تقریبا میشه گفت این فلویی هست که داره اتفاق میفته. اما این همیشه ثابت نیست یه سری از برنامه نویس ها ممکنه یه سری پارامتر های اضافه تری ارسال کن یا چیزای دیگه که خودشون اضافه کنن
اما چیزای که ما گفتیم ثابت هست و بخش اصلی فلوی oauth رو تشکیل میده. سعی کنید چند تا وبسایت رو بردارید و با استفاده از oauth لاگین کنید تا این مراحل به چشم ببینید.


راجب دوتا مقدار توی درخواست ها من چیزی نگفتم
این دوتا به نظرتون چیه و از کجا اومدن؟
client_id
client_secret
1
🕸 Articles
***این مرحله توسط کاربر دیده نمیشه*** مرحله 3: تبدیل Authorization Code به Access Token حالا سایت ما باید این Authorization Code رو به یه Access Token تبدیل کنه. 🔹 سایت یه درخواست POST می‌فرسته به سرور فیسبوک: POST https://graph.facebook.com/v12.0/oauth/access_token…
وقتی یه کاربر روی "ورود با Google" کلیک می‌کنه، فرآیند OAuth Authorization Code Flow (رایج‌ترین فلو) اجرا میشه. حالا، بعد از اینکه سرور OAuth به Client App یه Access Token میده، این توکن یا از نوع JWT هست یا Opaque

JWT (JSON Web Token)

یه توکن که داخلش اطلاعات کاربر هست و میشه بدون تماس به سرور، اعتبارش رو چک کرد.
کلاینت بدون نیاز به تماس با سرور OAuth، می‌تونه اطلاعات یوزر رو از داخل توکن استخراج کنه. چون JWT شامل اطلاعات کاربره، میشه از اون برای احراز هویت یوزر هم استفاده کرد.
هر کسی که این توکن رو داشته باشه، می‌تونه اطلاعاتش رو بخونه و بررسی کنه، اما نمی‌تونه تغییرش بده، چون امضاش چک می‌شه.
اگه لو بره، هر کسی می‌تونه ازش استفاده کنه تا زمانی که منقضی بشه.
🔹 بخش Payload شامل اطلاعاتی مثل user_id, exp (زمان انقضا), scopes (دسترسی‌ها) هست.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30


Opaque Token

یه رشته تصادفی و بدون معنیه که فقط Authorization Server می‌فهمه چی توشه.
کلاینت باید هر بار که می‌خواد از API استفاده کنه، توکن رو به سرور OAuth بفرسته تا اعتبارش رو چک کنه.
امنیت بیشتری داره چون کلاینت نمی‌تونه محتوای توکن رو ببینه.

c48a87f3-d5a4-42f3-84f5-9e5a2c62115b
3👍1
وقتی توی وبسایت وارد بخش login بشیم با این صفحه مواجه میشیم
من روی log in with google کلیک میکنم و یه درخواست ۳۰۲ ارسال میشه
به کجا ریداریکت میشیم؟ به گوگل
1
1
این صفحه بهمون نشون داده میشه
و آدرس ایمیل رو انتخاب میکنیم بعدش وارد صفحه دیگه میشیم که باید پسورد رو بزنیم
1
پسورد رو وارد میکنیم اینجا وقتی دکمه تایید بزنیم
بلافاصله وارد ریدارکت به وبسایتی که میخواستیم با استفاده از oauth واردش بشیم میشیم.
2
🕸 Articles
این صفحه بهمون نشون داده میشه و آدرس ایمیل رو انتخاب میکنیم بعدش وارد صفحه دیگه میشیم که باید پسورد رو بزنیم
GET /o/oauth2/auth?response_type=code&redirect_uri=https://quizlet.com/google-login&client_id=520305074949.apps.googleusercontent.com&scope=profile+email&access_type=online&approval_prompt=auto&state={"state":"kTWrjEKytCtTRyFhFbrf7G","reauth":false,"from":"\/goodbye","signupOrigin":"global-signup-modal-google","screenName":"logout\/logoutmobilesplash"}
2
🕸 Articles
پسورد رو وارد میکنیم اینجا وقتی دکمه تایید بزنیم بلافاصله وارد ریدارکت به وبسایتی که میخواستیم با استفاده از oauth واردش بشیم میشیم.
وقتی پسورد وارد میکنیم این ریدارکت انجام میشه که مارو به همراه یه سری اطلاعات دیگه میفرسته به کلاینت

https://quizlet.com/google-login?state={"state":"kTWrjEKytCtTRyFhFbrf7G","reauth":false,"from":"\/goodbye","signupOrigin":"global-signup-modal-google","screenName":"logout\/logoutmobilesplash"}&code=4/0AQSTgQFzS9eHAd2HHL9-GEX4BsDgucBYuBwWuOFhFp8puAa1TgAihhDnQITlvHKRo8TTdA&scope=email+profile+openid+https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/userinfo.profile&authuser=0&prompt=none
1👍1
وقتی وارد وبسایت میشیم این درخواست از سمت کلاینت زده میشه اینجا هست که وارد بخش
تبدیل Authorization Code به Access Token میشیم.

GET /google-login?state={"state":"kTWrjEKytCtTRyFhFbrf7G","reauth":false,"from":"\/goodbye","signupOrigin":"global-signup-modal-google","screenName":"logout\/logoutmobilesplash"}&code=4/0AQSTgQFzS9eHAd2HHL9-GEX4BsDgucBYuBwWuOFhFp8puAa1TgAihhDnQITlvHKRo8TTdA&scope=email+profile+openid+https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/userinfo.profile&authuser=0&prompt=none
1
و در نهایت access token داده میشه به کلاینت و ما توی وبسایت لاگین میشیم.
1
3
🕸 Articles
وقتی وارد وبسایت میشیم این درخواست از سمت کلاینت زده میشه اینجا هست که وارد بخش تبدیل Authorization Code به Access Token میشیم. GET /google-login?state={"state":"kTWrjEKytCtTRyFhFbrf7G","reauth":false,"from":"\/goodbye","signupOrigin":"global-signup-modal…
یه توضیح اضافه تر راجب اینکه چطوری کلاینت میاد و access token رو دریافت میکنه بگم

این مرحله توی مرورگر کاربر انجام نمیشه، بلکه کلاینت پشت‌صحنه یه درخواست دیگه به سرور OAuth می‌زنه
کلاینت این درخواست رو از سمت سرور خودش به Authorization Server (گوگل) می‌فرسته:

POST https://oauth2.googleapis.com/token
Content-Type: application/x-www-form-urlencoded

client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&code=4/0AQSTgQFzS9eHAd2HHL9-GEX4BsDgucBYuBwWuOFhFp8puAa1TgAihhDnQITlvHKRo8TTdA
&redirect_uri=https://yourwebsite.com/google-login
&grant_type=authorization_code


توی این درخواست، Authorization Code که از قبل توی URL بود، ارسال می‌شه به گوگل.
اگه این درخواست موفقیت‌آمیز باشه، گوگل یه Access Token برمی‌گردونه، مثل این:

{
"access_token": "ya29.A0AfH6SM...",
"expires_in": 3600,
"refresh_token": "1//0gQ...",
"scope": "email profile openid",
"token_type": "Bearer"
}
2
🕸 Articles
Photo
حالا که کلاینت Access Token داره، یه درخواست به ریسورس سرور (مثلاً API گوگل) می‌فرسته:

GET https://www.googleapis.com/oauth2/v3/userinfo
Authorization: Bearer ya29.A0AfH6SM...


ریسورس سرور (یعنی www.googleapis.com) بررسی می‌کنه که توکن معتبره یا نه،
اگه معتبر باشه، اطلاعات کاربر رو برمی‌گردونه:

{
"sub": "110169484474386276334",
"name": "zarvan0x01",
"given_name": "zarvan",
"family_name": "zurvanism",
"email": "zarvan@gmail.com",
"picture": "https://lh3.googleusercontent.com/a-/AOh14Gj..."
}


حالا کلاینت چیکار می‌کنه؟
اطلاعات کاربر رو ذخیره می‌کنه.
کاربر رو به حالت لاگین‌شده درمیاره.
احتمالاً یه سشن (Session) یا کوکی (Cookie) بسته به نوع پیاده سازیش برای کاربر ایجاد می‌کنه که لاگینش حفظ بشه.

و اینجوریه که کاربر بدون دیدن Access Token، لاگین می‌شه! توی این مرحله که ریپلای زدم اگر یادتون باشه بعد از ریدارکت به کلاینت یهو ما دیدیم که لاگین شدیم
ولی اون پشت برای لاگین شدن این درخواست ها هم زده شده
1
حالا اگر access token منقضی بشه چی؟

وقتی Access Token منقضی می‌شه، کلاینت باید این درخواست رو به Authorization Server بفرسته:
POST /token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
&client_id=your-client-id
&client_secret=your-client-secret


اگه Refresh Token معتبر باشه، سرور یه Access Token جدید می‌ده:

{
"access_token": "new-access-token-123",
"token_type": "Bearer",
"expires_in": 3600
}


حالا کلاینت از Access Token جدید برای درخواست‌هاش استفاده می‌کنه.
2