Giao diện
API Reference
Auth resource
Resource auth xử lý các thao tác xác thực. Các action được đăng ký trong actions/auth.ts và qua AuthManager.
signIn
Đăng nhập bằng authenticator đã chỉ định.
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/auth:signIn |
| ACL | Public (allow all) |
| Header | X-Authenticator: <tên authenticator> (ví dụ: basic) |
Request body:
json
{
"account": "admin",
"password": "your-password"
}Hoặc dùng email thay cho account:
json
{
"email": "admin@example.com",
"password": "your-password"
}Response (200):
json
{
"data": {
"user": { "id": 1, "username": "admin", "email": "admin@example.com" },
"token": "<JWT token>"
}
}Lỗi thường gặp:
| Status | Mô tả |
|---|---|
| 400 | Thiếu account/email — "Please enter your username or email" |
| 401 | Sai username/email hoặc password — internalCode INCORRECT_PASSWORD |
Luồng xử lý (BasicAuth.validate):
- Lấy
account(hoặcemail) vàpasswordtừ body - Tìm user theo
usernamehoặcemail(dùng$orquery) - So sánh password bằng
PasswordField.verify() - Trả về user object → core cấp JWT token
signUp
Đăng ký tài khoản mới.
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/auth:signUp |
| ACL | Public (allow all) |
| Header | X-Authenticator: <tên authenticator> |
Request body:
json
{
"username": "newuser",
"email": "newuser@example.com",
"password": "abc123",
"confirm_password": "abc123"
}Các trường khác trong signupForm config cũng có thể được gửi (ví dụ: nickname, phone).
Response (200):
json
{
"data": {
"user": { "id": 2, "username": "newuser" },
"token": "<JWT token>"
}
}Lỗi thường gặp:
| Status | Mô tả |
|---|---|
| 403 | Authenticator không cho phép đăng ký (allowSignUp: false) |
| 400 | Thiếu password, password không khớp confirm, username/email không hợp lệ |
Luồng xử lý (BasicAuth.signUp):
- Kiểm tra
options.public.allowSignUp === true - Đọc
signupFormsettings, validate các field bắt buộc - Kiểm tra
password === confirm_password - Tạo user mới qua
usersrepository
check
Kiểm tra phiên đăng nhập hiện tại.
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/auth:check |
| ACL | loggedIn |
| Header | Authorization: Bearer <token> |
Response (200):
json
{
"data": {
"id": 1,
"username": "admin",
"email": "admin@example.com"
}
}Nếu token hết hạn nhưng còn trong expiredTokenRenewLimit, server trả header x-new-token chứa token mới.
signOut
Đăng xuất, revoke token hiện tại.
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/auth:signOut |
| ACL | loggedIn |
| Header | Authorization: Bearer <token> |
Token bị thêm vào tokenBlacklist sau khi signOut.
lostPassword
Gửi email reset password.
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/auth:lostPassword |
| ACL | public |
| Header | X-Authenticator: <tên authenticator> |
Request body:
json
{
"email": "user@example.com",
"baseURL": "https://your-app.com"
}Response (200): null (thành công, email đã được gửi)
Lỗi thường gặp:
| Status | Mô tả |
|---|---|
| 400 | Thiếu email, email sai format, thiếu header X-Authenticator |
| 401 | Email không tồn tại trong hệ thống |
| 403 | Authenticator không bật enableResetPassword |
| 500 | Plugin notification-manager chưa cài, hoặc email channel không tìm thấy |
Luồng xử lý (BasicAuth.lostPassword):
- Validate email format
- Tìm user theo email
- Đọc config email từ authenticator options:
notificationChannel,emailSubject,emailContentType,emailContentHTML/emailContentText,resetTokenExpiresIn - Tạo JWT resetToken với payload
{ resetPasswordUserId }, hết hạn sauresetTokenExpiresInphút - Tạo link:
{baseURL}/reset-password?resetToken={token}&name={authenticatorName} - Parse template variables (
$user,$resetLink,$env,$resetLinkExpiration,$systemSettings) trong subject và content - Gửi email qua plugin
notification-manager
checkResetToken
Kiểm tra reset token còn hợp lệ không.
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/auth:checkResetToken |
| ACL | public |
Request body:
json
{
"resetToken": "<JWT reset token>"
}Response (200): true nếu token hợp lệ
Lỗi:
| Status | Mô tả |
|---|---|
| 401 | Token không tồn tại, đã hết hạn, hoặc đã bị dùng (nằm trong blacklist) |
Luồng xử lý (BasicAuth.checkResetToken):
- Kiểm tra token có trong blacklist không → reject nếu có
- Decode JWT, kiểm tra expiration → reject nếu hết hạn
resetPassword
Đặt lại mật khẩu bằng reset token.
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/auth:resetPassword |
| ACL | public |
Request body:
json
{
"resetToken": "<JWT reset token>",
"password": "new-password"
}Response (200): null (thành công)
Lỗi:
| Status | Mô tả |
|---|---|
| 401 | Token hết hạn hoặc đã dùng |
| 404 | User không tồn tại |
Luồng xử lý (BasicAuth.resetPassword):
- Gọi
checkResetToken()để validate - Decode token, lấy
resetPasswordUserId - Tìm user, cập nhật password
- Thêm resetToken vào blacklist (dùng 1 lần duy nhất)
changePassword
Đổi mật khẩu (yêu cầu đăng nhập).
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/auth:changePassword |
| ACL | loggedIn |
| Header | Authorization: Bearer <token> |
Request body:
json
{
"oldPassword": "current-password",
"newPassword": "new-password",
"confirmPassword": "new-password"
}Response (200): User object hiện tại
Lỗi:
| Status | Mô tả |
|---|---|
| 400 | newPassword khác confirmPassword |
| 401 | oldPassword không đúng, hoặc chưa đăng nhập |
| 403 | Hệ thống tắt tính năng đổi mật khẩu (systemSettings.enableChangePassword === false) |
Luồng xử lý:
- Kiểm tra
systemSettings.enableChangePassword - Lấy user hiện tại từ
ctx.auth.user - Verify
oldPasswordbằngPasswordField.verify() - Cập nhật password mới
Authenticators resource
Resource authenticators quản lý các phương thức xác thực. Hầu hết action yêu cầu ACL snippet pm.<plugin-name>.authenticators.
list
Lấy danh sách tất cả authenticator (admin).
| Chi tiết | |
|---|---|
| Method | GET |
| Path | /api/authenticators:list |
| ACL | pm.<plugin-name>.authenticators |
Trả về danh sách đầy đủ bao gồm cả authenticator chưa bật.
publicList
Lấy danh sách authenticator đã bật, dùng cho trang login.
| Chi tiết | |
|---|---|
| Method | GET |
| Path | /api/authenticators:publicList |
| ACL | Public (allow all) |
Response (200):
json
{
"data": [
{
"name": "basic",
"authType": "Email/Password",
"authTypeTitle": "Password",
"title": null,
"options": {
"allowSignUp": true,
"signupForm": [
{ "field": "username", "show": true, "required": true }
]
}
}
]
}Luồng xử lý:
- Query
authenticatorsvớifilter: { enabled: true }, chỉ lấyname, authType, title, options, sort - Với mỗi authenticator, gọi
authConfig.getPublicOptions(options)để lọc options an toàn cho client - Kết quả được sắp xếp theo trường
sort
listTypes
Lấy danh sách các loại authenticator đã đăng ký.
| Chi tiết | |
|---|---|
| Method | GET |
| Path | /api/authenticators:listTypes |
| ACL | pm.<plugin-name>.authenticators |
Response (200):
json
{
"data": [
{ "name": "Email/Password", "title": "Password" },
{ "name": "oidc", "title": "OIDC Login" }
]
}create
Tạo authenticator mới.
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/authenticators:create |
| ACL | pm.<plugin-name>.authenticators |
Dùng resource action mặc định của framework.
update
Cập nhật authenticator.
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/authenticators:update |
| ACL | pm.<plugin-name>.authenticators |
Lưu ý: Nếu values.enabled = false, server kiểm tra còn ít nhất 1 authenticator khác đang bật. Nếu đây là authenticator bật cuối cùng → trả lỗi 400: "Please keep and enable at least one authenticator".
destroy
Xóa authenticator.
| Chi tiết | |
|---|---|
| Method | POST |
| Path | /api/authenticators:destroy |
| ACL | pm.<plugin-name>.authenticators |
Lưu ý: Tương tự update, không cho phép xóa nếu chỉ còn 1 authenticator bật duy nhất.
Token policy config
Cấu hình token policy được lưu trong bảng tokenControlConfig.
| Chi tiết | |
|---|---|
| Resource | tokenControlConfig |
| ACL snippet | pm.security.token-policy |
Các tham số cấu hình
| Tham số | Mặc định | Mô tả |
|---|---|---|
tokenExpirationTime | '1d' | Thời hạn access token (hỗ trợ format ms: 1d, 2h, 30m...) |
sessionExpirationTime | '7d' | Thời hạn session — quá thời gian này kể từ lần signIn, token hoàn toàn hết hạn |
expiredTokenRenewLimit | '1d' | Khoảng thời gian cho phép gia hạn token sau khi token hết hạn |
Luồng gia hạn token (JTI renewal)
Client-side interceptor (Axios) đọc header x-new-token từ response và tự động thay thế token cũ.
Lưu ý kỹ thuật
TokenControllerdùngrandomUUID()để tạo JTI mới- Khi renew, JTI cũ được ghi đè bằng JTI mới trong bảng
issuedTokens(atomic update) - JTI mới được cache trong
RENEWED_JTI_CACHE_MS(10 giây) để xử lý concurrent request - Các
issuedTokenscósignInTimequásessionExpirationTimeđược tự động xóa khi có signIn mới