Bearer (phiên user) (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 user 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 user | Bearer (phiên user) ✅ |
| CRM thực hiện hành động under user context (vd "Sales A click-to-call") | Bearer (phiên user) ✅ |
| Server-to-server background job (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 user |
password | string | ✅ | Mật khẩu |
device_name | string | optional | Tên thiết bị / app để 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 + chọn permission 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.ZORIO_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 bị invalidate ngay — 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>Mọi token đang sống của user bị invalidate — dùng khi nghi ngờ tài khoản bị hack.
Thời hạn token
- Mặc định không tự expire — chỉ revoke thủ công.
- Có thể cấu hình expiration policy ở Admin Console: 30/60/90/180 ngày.
- Khi token expired/revoked → 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"]
}
}CRM có thể call endpoint này lúc khởi động để biết user hiện tại + check permission có sẵn.
Đổ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 KHÔNG bị invalidate — 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 ở vault (1Password, AWS Secrets Manager, Vault Hashicorp).
- Rotate token 90 ngày 1 lần.
- Mỗi app / thiết bị → tạo token riêng (
device_name) để dễ revoke targeted. - Catch 401 graceful → redirect user đến login page, không crash app.
