Bỏ qua, đến nội dung

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
MethodPOST
Path/api/auth:signIn
ACLPublic (allow all)
HeaderX-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:

StatusMô tả
400Thiếu account/email — "Please enter your username or email"
401Sai username/email hoặc password — internalCode INCORRECT_PASSWORD

Luồng xử lý (BasicAuth.validate):

  1. Lấy account (hoặc email) và password từ body
  2. Tìm user theo username hoặc email (dùng $or query)
  3. So sánh password bằng PasswordField.verify()
  4. Trả về user object → core cấp JWT token

signUp

Đăng ký tài khoản mới.

Chi tiết
MethodPOST
Path/api/auth:signUp
ACLPublic (allow all)
HeaderX-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:

StatusMô tả
403Authenticator không cho phép đăng ký (allowSignUp: false)
400Thiếu password, password không khớp confirm, username/email không hợp lệ

Luồng xử lý (BasicAuth.signUp):

  1. Kiểm tra options.public.allowSignUp === true
  2. Đọc signupForm settings, validate các field bắt buộc
  3. Kiểm tra password === confirm_password
  4. Tạo user mới qua users repository

check

Kiểm tra phiên đăng nhập hiện tại.

Chi tiết
MethodPOST
Path/api/auth:check
ACLloggedIn
HeaderAuthorization: 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
MethodPOST
Path/api/auth:signOut
ACLloggedIn
HeaderAuthorization: Bearer <token>

Token bị thêm vào tokenBlacklist sau khi signOut.


lostPassword

Gửi email reset password.

Chi tiết
MethodPOST
Path/api/auth:lostPassword
ACLpublic
HeaderX-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:

StatusMô tả
400Thiếu email, email sai format, thiếu header X-Authenticator
401Email không tồn tại trong hệ thống
403Authenticator không bật enableResetPassword
500Plugin notification-manager chưa cài, hoặc email channel không tìm thấy

Luồng xử lý (BasicAuth.lostPassword):

  1. Validate email format
  2. Tìm user theo email
  3. Đọc config email từ authenticator options: notificationChannel, emailSubject, emailContentType, emailContentHTML/emailContentText, resetTokenExpiresIn
  4. Tạo JWT resetToken với payload { resetPasswordUserId }, hết hạn sau resetTokenExpiresIn phút
  5. Tạo link: {baseURL}/reset-password?resetToken={token}&name={authenticatorName}
  6. Parse template variables ($user, $resetLink, $env, $resetLinkExpiration, $systemSettings) trong subject và content
  7. Gửi email qua plugin notification-manager

checkResetToken

Kiểm tra reset token còn hợp lệ không.

Chi tiết
MethodPOST
Path/api/auth:checkResetToken
ACLpublic

Request body:

json
{
  "resetToken": "<JWT reset token>"
}

Response (200): true nếu token hợp lệ

Lỗi:

StatusMô tả
401Token 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):

  1. Kiểm tra token có trong blacklist không → reject nếu có
  2. 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
MethodPOST
Path/api/auth:resetPassword
ACLpublic

Request body:

json
{
  "resetToken": "<JWT reset token>",
  "password": "new-password"
}

Response (200): null (thành công)

Lỗi:

StatusMô tả
401Token hết hạn hoặc đã dùng
404User không tồn tại

Luồng xử lý (BasicAuth.resetPassword):

  1. Gọi checkResetToken() để validate
  2. Decode token, lấy resetPasswordUserId
  3. Tìm user, cập nhật password
  4. 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
MethodPOST
Path/api/auth:changePassword
ACLloggedIn
HeaderAuthorization: Bearer <token>

Request body:

json
{
  "oldPassword": "current-password",
  "newPassword": "new-password",
  "confirmPassword": "new-password"
}

Response (200): User object hiện tại

Lỗi:

StatusMô tả
400newPassword khác confirmPassword
401oldPassword không đúng, hoặc chưa đăng nhập
403Hệ thống tắt tính năng đổi mật khẩu (systemSettings.enableChangePassword === false)

Luồng xử lý:

  1. Kiểm tra systemSettings.enableChangePassword
  2. Lấy user hiện tại từ ctx.auth.user
  3. Verify oldPassword bằng PasswordField.verify()
  4. 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
MethodGET
Path/api/authenticators:list
ACLpm.<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
MethodGET
Path/api/authenticators:publicList
ACLPublic (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ý:

  1. Query authenticators với filter: { enabled: true }, chỉ lấy name, authType, title, options, sort
  2. Với mỗi authenticator, gọi authConfig.getPublicOptions(options) để lọc options an toàn cho client
  3. 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
MethodGET
Path/api/authenticators:listTypes
ACLpm.<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
MethodPOST
Path/api/authenticators:create
ACLpm.<plugin-name>.authenticators

Dùng resource action mặc định của framework.


update

Cập nhật authenticator.

Chi tiết
MethodPOST
Path/api/authenticators:update
ACLpm.<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
MethodPOST
Path/api/authenticators:destroy
ACLpm.<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
ResourcetokenControlConfig
ACL snippetpm.security.token-policy

Các tham số cấu hình

Tham sốMặc địnhMô 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

  • TokenController dùng randomUUID() để 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 issuedTokenssignInTime quá sessionExpirationTime được tự động xóa khi có signIn mới