Giao diện
@digiforce-nc/auth
| Package | @digiforce-nc/auth |
| Import | import { AuthManager, Auth } from '@digiforce-nc/auth' |
Tổng quan
@digiforce-nc/auth là framework xác thực (authentication) của hệ thống Digiforce. Package cung cấp:
- AuthManager - đăng ký và quản lý nhiều kiểu xác thực (email/password, SSO, API key, ...).
- Auth (abstract) - lớp cơ sở cho từng kiểu xác thực, định nghĩa interface
check(),signIn(),signUp(). - JwtService - ký và verify JWT token, quản lý token lifecycle.
- TokenBlacklistService - revoke token đã cấp phát.
- Middleware - tích hợp vào Koa pipeline, tự động gán
ctx.state.currentUservàctx.state.currentRole.
Phân biệt Auth vs ACL
Auth xác thực "bạn là ai". ACL kiểm tra "bạn được làm gì". Auth chạy trước, đặt user/role vào context, sau đó ACL sử dụng thông tin này để kiểm tra quyền.
Kiến trúc tổng thể
AuthManager API
| Method | Mô tả |
|---|---|
jwt | Property - instance JwtService. Secret lấy từ options.authKey hoặc getDefaultJWTSecret() nếu không cấu hình. |
registerTypes(authType, authConfig) | Đăng ký kiểu xác thực. authType: tên duy nhất (ví dụ: 'Email/Password'). authConfig: { auth: AuthClass, title?: string }. |
setStorer(storer) | Bắt buộc gọi trước get(). storer đọc cấu hình authenticator từ database. |
setTokenBlacklistService(service) | Đăng ký service revoke token. |
setTokenControlService(service) | Đăng ký service kiểm soát token (renew, expire, concurrent sessions). |
get(name, ctx) | Tạo instance Auth dựa trên authenticator name + request context. Sử dụng storer để lấy config. |
middleware() | Trả về Koa middleware xác thực request - xem Auth middleware. |
Auth - lớp xác thực trừu tượng
Mỗi kiểu xác thực kế thừa Auth và implement các method:
| Method | Mô tả |
|---|---|
check() | Kiểm tra request hiện tại có hợp lệ không. Trả về User hoặc throw error. |
checkToken() | Kiểm tra trạng thái token (valid, expired, blacklisted). |
signIn() | Xử lý đăng nhập. Trả về token hoặc session info. |
signUp() | Xử lý đăng ký tài khoản mới. |
signOut() | Xử lý đăng xuất. Có thể blacklist token. |
validate() | Validate dữ liệu đầu vào (username, password format, ...). |
skipCheck() | Trả về true nếu action hiện tại không cần xác thực. |
user getter/setter | Get/set user model đã xác thực trên context. |
Tạo custom Auth type
typescript
import { Auth } from '@digiforce-nc/auth';
class ApiKeyAuth extends Auth {
async check() {
const apiKey = this.ctx.get('X-API-Key');
if (!apiKey) {
throw new AuthError('API key is required');
}
const user = await this.findUserByApiKey(apiKey);
if (!user) {
throw new AuthError('Invalid API key');
}
this.user = user;
return user;
}
async signIn() {
const { email, password } = this.ctx.request.body;
const user = await this.validateCredentials(email, password);
const apiKey = await this.generateApiKey(user);
return { apiKey };
}
private async findUserByApiKey(key: string) {
const repo = this.ctx.db.getRepository('apiKeys');
const record = await repo.findOne({ filter: { key, enabled: true } });
return record?.user;
}
}JwtService
JwtService quản lý toàn bộ lifecycle của JWT token.
| Method | Mô tả |
|---|---|
sign(payload, options?) | Ký JWT. payload thường chứa { userId }. options ghi đè expiresIn, algorithm. |
verify(token) | Verify và decode token. Throw error nếu expired/invalid. Kiểm tra blacklist nếu có. |
Token lifecycle
Auth middleware
Auth middleware được đăng ký vào Koa pipeline và chạy trước ACL middleware.
skipCheck() - bỏ qua xác thực
Một số route không cần xác thực (public API, health check, ...). Có thể đánh dấu bằng:
typescript
// Cách 1: Đăng ký resource là public trong ACL
acl.allow('app', 'getLang');
// Cách 2: Override skipCheck trong Auth class
class MyAuth extends Auth {
skipCheck() {
const publicPaths = ['/api/health', '/api/public/'];
return publicPaths.some(p => this.ctx.path.startsWith(p));
}
}Khi skipCheck() trả về true, middleware sẽ gọi next() mà không kiểm tra token.
Error codes
AuthErrorCode enum chứa các mã lỗi chuẩn:
| Code | Mô tả | HTTP Status |
|---|---|---|
EMPTY_TOKEN | Không tìm thấy token trong request | 401 |
INVALID_TOKEN | Token không hợp lệ hoặc đã hết hạn | 401 |
TOKEN_BLACKLISTED | Token đã bị revoke | 401 |
USER_NOT_FOUND | Token hợp lệ nhưng user không tồn tại | 401 |
USER_DISABLED | Tài khoản đã bị vô hiệu hoá | 403 |
INVALID_CREDENTIALS | Sai username/password | 401 |
AUTHENTICATOR_NOT_FOUND | Authenticator không tồn tại hoặc bị disable | 500 |
Token security
Token blacklist sử dụng cache làm storage mặc định. Trong production với multiple instances, phải dùng Redis-backed cache để đảm bảo blacklist đồng bộ giữa các instance.
Ví dụ tích hợp plugin
typescript
import { Plugin } from '@digiforce-nc/server';
import { Auth } from '@digiforce-nc/auth';
class OAuthAuth extends Auth {
async check() {
const token = this.ctx.getBearerToken();
const payload = await this.ctx.app.authManager.jwt.verify(token);
const user = await this.ctx.db.getRepository('users').findOne({
filter: { id: payload.userId },
});
if (!user) throw new Error('User not found');
this.user = user;
return user;
}
async signIn() {
const { code, redirectUri } = this.ctx.request.body;
const oauthUser = await this.exchangeCodeForUser(code, redirectUri);
let user = await this.findOrCreateUser(oauthUser);
const token = this.ctx.app.authManager.jwt.sign({ userId: user.id });
return { token, user };
}
async signOut() {
const token = this.ctx.getBearerToken();
await this.ctx.app.authManager.jwt.blacklist?.add(token);
}
}
class MyOAuthPlugin extends Plugin {
async load() {
this.app.authManager.registerTypes('OAuth', {
auth: OAuthAuth,
title: 'OAuth 2.0',
});
}
}Phụ thuộc
| Package | Vai trò |
|---|---|
@digiforce-nc/actions | Cung cấp action handler cho auth routes (signIn, signUp, ...) |
@digiforce-nc/cache | Backend cho TokenBlacklistService |
@digiforce-nc/database | Đọc user, authenticator config từ DB |
@digiforce-nc/resourcer | Đăng ký auth resource/action vào router |
Đọc thêm
- Auth & AuthManager - phân tích chi tiết source code, middleware flow, token lifecycle.
- ACL Engine - hệ thống phân quyền chạy sau Auth.
- Server Application - cách AuthManager tích hợp vào Application.
- Mã nguồn