Authentication và Authorization trong NestJS – JWT & Guards nâng cao

3 min read

🔐 Authentication và Authorization trong NestJS – JWT & Guards nâng cao

🧭 Giới thiệu

Trong các ứng dụng backend hiện đại, Authentication (xác thực) và Authorization (phân quyền) là hai phần quan trọng nhất để bảo vệ dữ liệu người dùng.
NestJS hỗ trợ sẵn các công cụ mạnh mẽ như Passport, JWTGuards, giúp bạn xây dựng hệ thống bảo mật chặt chẽ mà vẫn dễ mở rộng.

Bài viết này sẽ hướng dẫn chi tiết cách:

  • Tạo cơ chế đăng nhập bằng JWT.
  • Dùng Passport để xác thực người dùng.
  • Tạo Guard tùy chỉnh để phân quyền linh hoạt.
  • Tối ưu bảo mật với Refresh Token và Middleware.

🧩 Authentication và Authorization là gì?

Trước tiên, cần phân biệt rõ:

  • Authentication: Xác thực danh tính người dùng (bạn là ai?).
  • Authorization: Kiểm tra quyền truy cập (bạn được làm gì?).

Hai bước này luôn đi cùng nhau.
Ví dụ: Một người dùng đã đăng nhập (authenticated) có thể chỉ được xem dữ liệu, nhưng không được xóa (authorization).


⚙️ Thiết lập JWT trong NestJS

JWT (JSON Web Token) giúp xác thực người dùng mà không cần lưu session server-side.

1️⃣ Cài đặt package cần thiết

npm install @nestjs/jwt @nestjs/passport passport passport-jwt bcrypt

2️⃣ Tạo AuthModule

@Module({
  imports: [
    JwtModule.register({
      secret: process.env.JWT_SECRET,
      signOptions: { expiresIn: '1h' },
    }),
  ],
  providers: [AuthService, JwtStrategy],
  controllers: [AuthController],
})
export class AuthModule {}

3️⃣ Tạo AuthService

@Injectable()
export class AuthService {
  constructor(private jwtService: JwtService) {}

  async login(user: any) {
    const payload = { username: user.email, sub: user.id };
    return {
      access_token: this.jwtService.sign(payload),
    };
  }
}

4️⃣ Cấu hình chiến lược Passport JWT

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: process.env.JWT_SECRET,
    });
  }

  async validate(payload: any) {
    return { userId: payload.sub, email: payload.username };
  }
}

🧠 Sử dụng Guards để bảo vệ route

Guard trong NestJS giúp chặn hoặc cho phép request trước khi tới controller.

Ví dụ: JwtAuthGuard

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

Áp dụng vào route:

@UseGuards(JwtAuthGuard)
@Get('profile')
getProfile(@Request() req) {
  return req.user;
}

Tạo Guard phân quyền (RoleGuard)

@Injectable()
export class RolesGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    return user?.role === 'admin';
  }
}

Sử dụng Guard kết hợp:

@UseGuards(JwtAuthGuard, RolesGuard)
@Get('admin')
getAdminPage() {
  return 'Welcome admin!';
}

🔁 Refresh Token – Giữ đăng nhập an toàn

Để tránh việc người dùng bị đăng xuất mỗi khi token hết hạn, ta sử dụng refresh token.

Ví dụ:

  • Khi đăng nhập, API trả về access_tokenrefresh_token.
  • access_token có thời hạn ngắn (1h), refresh_token có thời hạn dài hơn (7d).
  • Khi access_token hết hạn, người dùng gọi API refresh để lấy token mới.

✅ Ưu điểm của cơ chế bảo mật trong NestJS

Tính năngMô tả
ModularDễ mở rộng với nhiều chiến lược xác thực khác nhau.
SecureSử dụng JWT giúp giảm phụ thuộc session.
FlexibleCó thể tạo guard tùy chỉnh cho từng use case.
ScalableDễ áp dụng cho microservices.

⚠️ Các lỗi thường gặp

LỗiCách khắc phục
Token không hợp lệKiểm tra JWT_SECRET đồng nhất giữa sign và verify.
Token hết hạn sớmĐiều chỉnh expiresIn phù hợp.
Không inject được JwtServiceĐảm bảo JwtModule được import đúng module.
Guard không chạyKiểm tra decorator @UseGuards() có được áp dụng.

🔗 Tham khảo thêm


🚀 Kết luận

Nhờ Passport, JWTGuards, NestJS giúp bạn xây dựng hệ thống xác thực và phân quyền linh hoạt, mạnh mẽ mà vẫn giữ cấu trúc rõ ràng.
Hơn nữa, việc tách riêng từng phần giúp bạn dễ bảo trì, dễ mở rộng, và đảm bảo an toàn cho ứng dụng của mình.
Vì vậy, hãy bắt đầu chuẩn hóa cơ chế bảo mật ngay từ hôm nay.

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *