Skip to content

Route BFF

Route Nitro mà @tasco/nuxt-layer-base mang theo. Trình duyệt chỉ gọi các route này, không gọi thẳng IAM hay backend. Luồng tổng thể: BFF: /api/** đi đâuPhiên đăng nhập.

MethodĐường dẫnFile trong layerViệc
Mọi method/api/**server/api/[...].tsChuyển tiếp tới backend, gắn token của phiên
POST/auth/loginserver/routes/auth/login.post.tsĐổi tài khoản lấy token, tạo phiên
GET/auth/sessionserver/routes/auth/session.get.tsNgười dùng của phiên hiện tại
GET/auth/clientsserver/routes/auth/clients.get.tsDanh sách ứng dụng cho form đăng nhập
POST/auth/otp/sendserver/routes/auth/otp/send.post.tsGửi OTP qua Telegram
GET/auth/logoutserver/routes/auth/logout.get.tsXoá phiên rồi chuyển hướng

GET /auth/login không phải route server mà là trang Vue app/pages/auth/login.vue — cùng đường dẫn, khác method.

Lỗi do chính các route này ném ra có dạng lỗi của h3: mã HTTP ở statusCode, thông báo tiếng Việt ở statusMessage. Phía client đọc qua AppError (status, message) — xem AppError & phân loại.

/api/**

Request: giữ nguyên method, query, body và header, trừ:

PhầnXử lý
Đường dẫnBỏ tiền tố /api, nối vào apiProxyTarget (bỏ / thừa ở cuối target): /api/orders?page=1<target>/orders?page=1
authorizationHeader client gửi bị xoá. Phiên có token còn hạn → Authorization: Bearer <token>
cookieLuôn bị xoá — cookie trình duyệt, kể cả tasco_session, không sang backend

Response: nguyên trạng status, header và body của backend.

Tình huốngKết quả
Chưa đặt NUXT_API_PROXY_TARGET500 apiProxyTarget chưa cấu hình.
Chưa đăng nhập, hoặc token đã hết hạn (expiresAt)Chuyển tiếp không kèm Authorization — backend tự trả 401

Route cụ thể trong server/api/ của dự án (vd server/api/orders/summary.get.ts) thắng catch-all này.

POST /auth/login

Body (LoginCredentials):

FieldKiểuBắt buộcÝ nghĩa
usernamestringCắt khoảng trắng hai đầu
passwordstring
clientIdstringKhôngMã ứng dụng (AuthClientOption.code)
method'google' | 'telegram'KhôngPhương thức OTP; đổi sang mã auth.authenMethod.* khi gửi IAM
otpstringKhôngMã OTP
transactionIdstringKhôngTrả về từ POST /auth/otp/send

Response 200: { user: AuthUser } — người dùng đầy đủ roles và permissions lấy từ userInfo. Đồng thời đặt cookie tasco_session.

LỗiKhi
400 Thiếu tên đăng nhập hoặc mật khẩu.Thiếu username (sau khi cắt khoảng trắng) hoặc password
401 kèm thông báo của IAMIAM trả code khác API000 — sai mật khẩu, sai OTP…
500 auth.baseURL chưa cấu hình (NUXT_AUTH_BASE_URL).Chưa cấu hình IAM và không bật mock
500IAM không trả access token ở auth.mapping.token

Mock (NUXT_AUTH_MOCK=true): không gọi IAM, nhận mọi tài khoản và trả:

json
{
  "user": {
    "id": "mock-user",
    "name": "Người dùng <username>",
    "email": "<username>@tasco.vn",
    "roles": ["admin"],
    "permissions": ["/orders/search", "/orders/create", "/orders/update"]
  }
}

Gọi IAM có timeout 10 giây. BFF tự sinh các field thiết bị IAM yêu cầu (deviceId, deviceUuid…).

GET /auth/session

Response 200: { user: AuthUser | null }. Route không ném lỗi xác thực — mọi trường hợp không có phiên hợp lệ đều trả user: null.

Tình huốnguser
Không có cookie, cookie sai hoặc bị sửanull
Phiên có tokenGọi lại userInfo bằng token → người dùng đầy đủ quyền
userInfo lỗi (token hết hạn, IAM từ chối)null
Mock, hoặc phiên không có tokenNgười dùng lưu trong cookie

Plugin 02.auth gọi route này một lần khi app khởi động để nạp useState('tasco:auth:user').

GET /auth/clients

Response 200: { clients: AuthClientOption[] } — chỉ giữ ứng dụng có đủ id, code, name.

Tình huốngclients
auth.endpoints.clients rỗng[]
MockHai ứng dụng mẫu OAP_OCM, OAP_CUS

Không yêu cầu đăng nhập (form đăng nhập gọi route này).

POST /auth/otp/send

Body: { username: string, password: string, clientId?: string }.

Response 200: { transactionId?: string } — gửi kèm POST /auth/login. Chỉ Telegram cần bước này; Google Authenticator thì nhập mã thẳng.

LỗiKhi
400 Thiếu tên đăng nhập hoặc mật khẩu.Thiếu username hoặc password
400 Chưa cấu hình gửi OTP (auth.endpoints.otpSend).Endpoint gửi OTP để rỗng
401 kèm thông báo của IAMIAM từ chối

Mock trả { transactionId: 'mock-transaction' }.

GET /auth/logout

Query: redirect — đường dẫn quay về sau khi đăng xuất, mặc định /.

Xoá cookie tasco_session rồi trả 302. redirect chỉ nhận đường dẫn nội bộ: phải bắt đầu bằng đúng một /; //evil.com, /\evil.com hay URL tuyệt đối đều thành / (chống open redirect). Đây là điều hướng của trình duyệt, không gọi bằng $fetchuseAuth().logout() làm việc đó.

Thuộc tínhGiá trị
Nội dung{ user, accessToken?, expiresAt? }. Đăng nhập thật: user chỉ giữ id, name, email, roles và permissions lấy tươi ở /auth/session. Mock: cả người dùng giả, không có token
Định dạngv1.<iv>.<ciphertext>.<tag> (base64url), mã hoá và ký AES-256-GCM bằng khoá suy từ NUXT_SESSION_SECRET
CờHttpOnly, SameSite=Lax, Path=/, Secure (trừ khi chạy dev)
Thời hạn8 giờ; không có refresh token — hết hạn thì đăng nhập lại

Cookie giới hạn 4KB và access token IAM đã khoảng 2,4KB, nên không thêm dữ liệu vào phiên.

Liên quan