331 lines
9.4 KiB
Markdown
331 lines
9.4 KiB
Markdown
|
# مستندات OAuth Hesabix
|
||
|
|
||
|
## مقدمه
|
||
|
|
||
|
Hesabix از پروتکل OAuth 2.0 برای احراز هویت برنامههای خارجی استفاده میکند. این مستندات نحوه پیادهسازی OAuth در برنامههای شما را توضیح میدهد.
|
||
|
|
||
|
## مراحل پیادهسازی
|
||
|
|
||
|
### 1. ثبت برنامه
|
||
|
|
||
|
ابتدا باید برنامه خود را در پنل مدیریت Hesabix ثبت کنید:
|
||
|
|
||
|
1. وارد پنل مدیریت شوید
|
||
|
2. به بخش "تنظیمات سیستم" بروید
|
||
|
3. تب "برنامههای OAuth" را انتخاب کنید
|
||
|
4. روی "برنامه جدید" کلیک کنید
|
||
|
5. اطلاعات برنامه را وارد کنید:
|
||
|
- نام برنامه
|
||
|
- توضیحات
|
||
|
- آدرس وبسایت
|
||
|
- آدرس بازگشت (Redirect URI)
|
||
|
- محدودههای دسترسی مورد نیاز
|
||
|
|
||
|
### 2. دریافت Client ID و Client Secret
|
||
|
|
||
|
پس از ثبت برنامه، Client ID و Client Secret به شما داده میشود. این اطلاعات را در جای امنی ذخیره کنید.
|
||
|
|
||
|
## محدودههای دسترسی (Scopes)
|
||
|
|
||
|
| Scope | توضیحات |
|
||
|
|-------|---------|
|
||
|
| `read_profile` | دسترسی به اطلاعات پروفایل کاربر |
|
||
|
| `write_profile` | ویرایش اطلاعات پروفایل کاربر |
|
||
|
| `read_business` | دسترسی به اطلاعات کسبوکار |
|
||
|
| `write_business` | ویرایش اطلاعات کسبوکار |
|
||
|
| `read_accounting` | دسترسی به اطلاعات حسابداری |
|
||
|
| `write_accounting` | ویرایش اطلاعات حسابداری |
|
||
|
| `read_reports` | دسترسی به گزارشها |
|
||
|
| `write_reports` | ایجاد و ویرایش گزارشها |
|
||
|
| `admin` | دسترسی مدیریتی کامل |
|
||
|
|
||
|
## OAuth Flow
|
||
|
|
||
|
### Authorization Code Flow (توصیه شده)
|
||
|
|
||
|
#### مرحله 1: درخواست مجوز
|
||
|
|
||
|
کاربر را به آدرس زیر هدایت کنید:
|
||
|
|
||
|
```
|
||
|
GET /oauth/authorize
|
||
|
```
|
||
|
|
||
|
پارامترهای مورد نیاز:
|
||
|
- `client_id`: شناسه برنامه شما
|
||
|
- `redirect_uri`: آدرس بازگشت (باید با آدرس ثبت شده مطابقت داشته باشد)
|
||
|
- `response_type`: همیشه `code`
|
||
|
- `scope`: محدودههای دسترسی (با فاصله جدا شده)
|
||
|
- `state`: مقدار تصادفی برای امنیت (اختیاری)
|
||
|
|
||
|
مثال:
|
||
|
```
|
||
|
https://hesabix.ir/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=https://yourapp.com/callback&response_type=code&scope=read_profile%20read_business&state=random_string
|
||
|
```
|
||
|
|
||
|
#### مرحله 2: دریافت کد مجوز
|
||
|
|
||
|
پس از تایید کاربر، به آدرس `redirect_uri` با پارامتر `code` هدایت میشود:
|
||
|
|
||
|
```
|
||
|
https://yourapp.com/callback?code=AUTHORIZATION_CODE&state=random_string
|
||
|
```
|
||
|
|
||
|
#### مرحله 3: دریافت توکن دسترسی
|
||
|
|
||
|
کد مجوز را با Client Secret مبادله کنید:
|
||
|
|
||
|
```bash
|
||
|
curl -X POST https://hesabix.ir/oauth/token \
|
||
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
||
|
-d "grant_type=authorization_code" \
|
||
|
-d "client_id=YOUR_CLIENT_ID" \
|
||
|
-d "client_secret=YOUR_CLIENT_SECRET" \
|
||
|
-d "code=AUTHORIZATION_CODE" \
|
||
|
-d "redirect_uri=https://yourapp.com/callback"
|
||
|
```
|
||
|
|
||
|
پاسخ:
|
||
|
```json
|
||
|
{
|
||
|
"access_token": "ACCESS_TOKEN",
|
||
|
"token_type": "Bearer",
|
||
|
"expires_in": 3600,
|
||
|
"refresh_token": "REFRESH_TOKEN",
|
||
|
"scope": "read_profile read_business"
|
||
|
}
|
||
|
```
|
||
|
|
||
|
### استفاده از توکن دسترسی
|
||
|
|
||
|
برای دسترسی به API ها، توکن را در header قرار دهید:
|
||
|
|
||
|
```bash
|
||
|
curl -H "Authorization: Bearer ACCESS_TOKEN" \
|
||
|
https://hesabix.ir/oauth/userinfo
|
||
|
```
|
||
|
|
||
|
## API Endpoints
|
||
|
|
||
|
### اطلاعات کاربر
|
||
|
|
||
|
```
|
||
|
GET /oauth/userinfo
|
||
|
Authorization: Bearer ACCESS_TOKEN
|
||
|
```
|
||
|
|
||
|
پاسخ:
|
||
|
```json
|
||
|
{
|
||
|
"sub": 123,
|
||
|
"email": "user@example.com",
|
||
|
"name": "نام کاربر",
|
||
|
"mobile": "09123456789",
|
||
|
"profile": {
|
||
|
"full_name": "نام کامل",
|
||
|
"mobile": "09123456789",
|
||
|
"email": "user@example.com",
|
||
|
"date_register": "2024-01-01",
|
||
|
"active": true
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
### تمدید توکن
|
||
|
|
||
|
```bash
|
||
|
curl -X POST https://hesabix.ir/oauth/token \
|
||
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
||
|
-d "grant_type=refresh_token" \
|
||
|
-d "client_id=YOUR_CLIENT_ID" \
|
||
|
-d "client_secret=YOUR_CLIENT_SECRET" \
|
||
|
-d "refresh_token=REFRESH_TOKEN"
|
||
|
```
|
||
|
|
||
|
### لغو توکن
|
||
|
|
||
|
```bash
|
||
|
curl -X POST https://hesabix.ir/oauth/revoke \
|
||
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
||
|
-d "token=ACCESS_TOKEN" \
|
||
|
-d "token_type_hint=access_token"
|
||
|
```
|
||
|
|
||
|
## Discovery Endpoint
|
||
|
|
||
|
برای دریافت اطلاعات OAuth server:
|
||
|
|
||
|
```
|
||
|
GET /.well-known/oauth-authorization-server
|
||
|
```
|
||
|
|
||
|
پاسخ:
|
||
|
```json
|
||
|
{
|
||
|
"issuer": "https://hesabix.ir",
|
||
|
"authorization_endpoint": "https://hesabix.ir/oauth/authorize",
|
||
|
"token_endpoint": "https://hesabix.ir/oauth/token",
|
||
|
"userinfo_endpoint": "https://hesabix.ir/oauth/userinfo",
|
||
|
"revocation_endpoint": "https://hesabix.ir/oauth/revoke",
|
||
|
"response_types_supported": ["code"],
|
||
|
"grant_types_supported": ["authorization_code", "refresh_token"],
|
||
|
"token_endpoint_auth_methods_supported": ["client_secret_post"],
|
||
|
"scopes_supported": [
|
||
|
"read_profile",
|
||
|
"write_profile",
|
||
|
"read_business",
|
||
|
"write_business",
|
||
|
"read_accounting",
|
||
|
"write_accounting",
|
||
|
"read_reports",
|
||
|
"write_reports",
|
||
|
"admin"
|
||
|
]
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## نکات امنیتی
|
||
|
|
||
|
1. **HTTPS اجباری**: تمام ارتباطات باید روی HTTPS باشد
|
||
|
2. **State Parameter**: همیشه از state parameter استفاده کنید
|
||
|
3. **توکنهای کوتاهمدت**: توکنهای دسترسی 1 ساعت اعتبار دارند
|
||
|
4. **Refresh Token**: برای تمدید توکن از refresh token استفاده کنید
|
||
|
5. **Client Secret**: Client Secret را در کد سمت کلاینت قرار ندهید
|
||
|
|
||
|
## مثال پیادهسازی (JavaScript)
|
||
|
|
||
|
```javascript
|
||
|
class HesabixOAuth {
|
||
|
constructor(clientId, redirectUri) {
|
||
|
this.clientId = clientId;
|
||
|
this.redirectUri = redirectUri;
|
||
|
this.baseUrl = 'https://hesabix.ir';
|
||
|
}
|
||
|
|
||
|
// شروع فرآیند OAuth
|
||
|
authorize(scopes = ['read_profile']) {
|
||
|
const state = this.generateState();
|
||
|
const params = new URLSearchParams({
|
||
|
client_id: this.clientId,
|
||
|
redirect_uri: this.redirectUri,
|
||
|
response_type: 'code',
|
||
|
scope: scopes.join(' '),
|
||
|
state: state
|
||
|
});
|
||
|
|
||
|
localStorage.setItem('oauth_state', state);
|
||
|
window.location.href = `${this.baseUrl}/oauth/authorize?${params}`;
|
||
|
}
|
||
|
|
||
|
// پردازش callback
|
||
|
async handleCallback() {
|
||
|
const urlParams = new URLSearchParams(window.location.search);
|
||
|
const code = urlParams.get('code');
|
||
|
const state = urlParams.get('state');
|
||
|
const savedState = localStorage.getItem('oauth_state');
|
||
|
|
||
|
if (state !== savedState) {
|
||
|
throw new Error('State mismatch');
|
||
|
}
|
||
|
|
||
|
if (!code) {
|
||
|
throw new Error('Authorization code not found');
|
||
|
}
|
||
|
|
||
|
const tokens = await this.exchangeCode(code);
|
||
|
localStorage.setItem('access_token', tokens.access_token);
|
||
|
localStorage.setItem('refresh_token', tokens.refresh_token);
|
||
|
|
||
|
return tokens;
|
||
|
}
|
||
|
|
||
|
// مبادله کد با توکن
|
||
|
async exchangeCode(code) {
|
||
|
const response = await fetch(`${this.baseUrl}/oauth/token`, {
|
||
|
method: 'POST',
|
||
|
headers: {
|
||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||
|
},
|
||
|
body: new URLSearchParams({
|
||
|
grant_type: 'authorization_code',
|
||
|
client_id: this.clientId,
|
||
|
client_secret: 'YOUR_CLIENT_SECRET', // در سرور ذخیره شود
|
||
|
code: code,
|
||
|
redirect_uri: this.redirectUri
|
||
|
})
|
||
|
});
|
||
|
|
||
|
if (!response.ok) {
|
||
|
throw new Error('Token exchange failed');
|
||
|
}
|
||
|
|
||
|
return await response.json();
|
||
|
}
|
||
|
|
||
|
// دریافت اطلاعات کاربر
|
||
|
async getUserInfo() {
|
||
|
const token = localStorage.getItem('access_token');
|
||
|
const response = await fetch(`${this.baseUrl}/oauth/userinfo`, {
|
||
|
headers: {
|
||
|
'Authorization': `Bearer ${token}`
|
||
|
}
|
||
|
});
|
||
|
|
||
|
if (!response.ok) {
|
||
|
throw new Error('Failed to get user info');
|
||
|
}
|
||
|
|
||
|
return await response.json();
|
||
|
}
|
||
|
|
||
|
// تمدید توکن
|
||
|
async refreshToken() {
|
||
|
const refreshToken = localStorage.getItem('refresh_token');
|
||
|
const response = await fetch(`${this.baseUrl}/oauth/token`, {
|
||
|
method: 'POST',
|
||
|
headers: {
|
||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||
|
},
|
||
|
body: new URLSearchParams({
|
||
|
grant_type: 'refresh_token',
|
||
|
client_id: this.clientId,
|
||
|
client_secret: 'YOUR_CLIENT_SECRET',
|
||
|
refresh_token: refreshToken
|
||
|
})
|
||
|
});
|
||
|
|
||
|
if (!response.ok) {
|
||
|
throw new Error('Token refresh failed');
|
||
|
}
|
||
|
|
||
|
const tokens = await response.json();
|
||
|
localStorage.setItem('access_token', tokens.access_token);
|
||
|
localStorage.setItem('refresh_token', tokens.refresh_token);
|
||
|
|
||
|
return tokens;
|
||
|
}
|
||
|
|
||
|
generateState() {
|
||
|
return Math.random().toString(36).substring(2, 15);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// استفاده
|
||
|
const oauth = new HesabixOAuth('YOUR_CLIENT_ID', 'https://yourapp.com/callback');
|
||
|
|
||
|
// شروع OAuth
|
||
|
oauth.authorize(['read_profile', 'read_business']);
|
||
|
|
||
|
// در صفحه callback
|
||
|
oauth.handleCallback().then(tokens => {
|
||
|
console.log('OAuth successful:', tokens);
|
||
|
// دریافت اطلاعات کاربر
|
||
|
return oauth.getUserInfo();
|
||
|
}).then(userInfo => {
|
||
|
console.log('User info:', userInfo);
|
||
|
});
|
||
|
```
|
||
|
|
||
|
## پشتیبانی
|
||
|
|
||
|
برای سوالات و مشکلات مربوط به OAuth، با تیم پشتیبانی Hesabix تماس بگیرید.
|