Bearer Token (User Session)
Bearer Token (phiên user) là cơ chế xác thực gắn với phiên đăng nhập của người dùng trên trang Admin Console. Phù hợp cho các ứng dụng tích hợp có người dùng cuối (frontend, dashboard nội bộ, app mobile riêng).
Khi nào dùng Bearer (phiên user)?
| Use case | Cơ chế phù hợp |
|---|---|
| Frontend (Vue/React/Mobile) gọi API thay mặt người dùng | Bearer (phiên user) ✅ |
| CRM thực hiện hành động theo ngữ cảnh của người dùng (vd "Sales A click-to-call") | Bearer (phiên user) ✅ |
| Tác vụ server-to-server chạy nền (không có user) | API Token |
| Webhook receiver verify Zorio đẩy event | Ký HMAC-SHA256 |
Lấy token
Cách 1 — Đăng nhập qua API
Endpoint: POST /api/auth/login
Request body
| Field | Type | Required | Mô tả |
|---|---|---|---|
username | string | ✅ | Tên đăng nhập của người dùng |
password | string | ✅ | Mật khẩu |
device_name | string | optional | Tên thiết bị hoặc ứng dụng để phân biệt token (vd CRM-Salesforce, iPhone-Sales-01) |
{
"username": "sales01",
"password": "...",
"device_name": "CRM-Salesforce"
}Response 200
{
"data": {
"user": {
"id": 7,
"username": "sales01",
"email": "sales01@example.com",
"role": "agent",
"team_id": 2
}
},
"token": "12|abcdefghijklmnopqrstuvwxyz0123456789"
}Lưu token ngay vào storage an toàn (httpOnly cookie hoặc Keychain mobile). Token là chuỗi <id>|<random>.
Response 401
{ "message": "Sai tài khoản hoặc mật khẩu." }Response 422
{
"message": "The given data was invalid.",
"errors": {
"username": ["Trường username là bắt buộc."]
}
}Cách 2 — Tạo token qua Admin Console
Vào Cài đặt → API Tokens → bấm Tạo token mới → đặt tên và chọn phạm vi quyền (scope). Token chỉ hiển thị 1 lần — copy ngay.
Dùng token trong request
Mọi request kèm 2 header:
Authorization: Bearer <token>
Accept: application/jsonVí dụ cURL
curl -X GET 'https://app.zorio.vn/api/pbx/extensions' \
-H 'Authorization: Bearer 12|abcdefghijklmnopqrstuvwxyz' \
-H 'Accept: application/json'Ví dụ Node.js (axios)
const axios = require('axios');
const api = axios.create({
baseURL: 'https://app.zorio.vn/api',
headers: {
Authorization: 'Bearer ' + process.env.OMNISERVE_TOKEN,
Accept: 'application/json',
},
});
const res = await api.get('/pbx/extensions');
console.log(res.data);Ví dụ PHP (Guzzle)
$client = new GuzzleHttp\Client([
'base_uri' => 'https://app.zorio.vn/api/',
'headers' => [
'Authorization' => 'Bearer ' . getenv('ZORIO_TOKEN'),
'Accept' => 'application/json',
],
]);
$res = $client->get('pbx/extensions');Logout / Revoke
Logout phiên hiện tại
POST /api/auth/logout
Authorization: Bearer <token>Trả 200 { "data": { "logged_out": true } }. Token sẽ bị vô hiệu hóa ngay lập tức — request sau dùng token này → 401.
Revoke 1 token cụ thể (admin)
Vào Admin Console → API Tokens → bấm Revoke bên cạnh token cần xoá.
Revoke tất cả token của user (logout-all)
POST /api/auth/logout-all
Authorization: Bearer <token>Tất cả token còn hiệu lực của người dùng bị invalidate — dùng khi nghi ngờ tài khoản có dấu hiệu bị xâm nhập.
Thời hạn token
- Mặc định không tự hết hạn — chỉ revoke thủ công.
- Có thể cấu hình chính sách hết hạn ở Admin Console: 30/60/90/180 ngày.
- Khi token hết hạn hoặc bị thu hồi → API trả HTTP 401 với body
{ "message": "Unauthenticated." }.
Whoami (kiểm tra token)
GET /api/auth/me
Authorization: Bearer <token>Response 200:
{
"data": {
"id": 7,
"username": "sales01",
"email": "sales01@example.com",
"role": "agent",
"team_id": 2,
"permissions": ["pbx_api_access", "telesales_make_call", "view_my_cdr"]
}
}Ứng dụng có thể gọi endpoint này lúc khởi động để biết user hiện tại + kiểm tra các quyền hiện có.
Đổi mật khẩu
POST /api/auth/change-password
Authorization: Bearer <token>
{
"current_password": "...",
"new_password": "...",
"new_password_confirmation": "..."
}Response 200 { "data": { "changed": true } }. Token hiện tại vẫn còn hiệu lực — user vẫn duy trì phiên.
Best practice
- Không hardcode token trong code frontend (bị lộ qua DevTools).
- KHÔNG commit token vào git.
- Token dài hạn → lưu ở Secret Manager hoặc hệ thống quản lý bí mật (1Password, AWS Secrets Manager, Vault Hashicorp).
- Nên thay đổi (rotate) token định kỳ, ví dụ mỗi 90 ngày..
- Mỗi app / thiết bị → tạo token riêng (
device_name) để dễ thu hồi đúng token của từng thiết bị. - Khi nhận HTTP 401, chuyển người dùng về trang đăng nhập và xử lý lỗi an toàn, tránh làm gián đoạn ứng dụng.
