Tiếp tục series hướng dẫn dev Full stack developer Web application. Như các bạn đã biết, ở Phần 1 mình đã giúp các bạn cài đặt và tạo api Articles với NestJS. Thì phần này, chúng ta sẽ cùng tìm hiểu Về Auth0, và mình sẽ hướng dẫn các bạn làm thế nào để cấu hình và cài đặt Auth0 để xác thưc NestJS API.

I. Giới thiệu về Auth0

  • Auth0 là một dịch vụ quản lý xác thực và ủy quyền dựa trên đám mây, giúp cho việc xây dựng các hệ thống xác thực an toàn và dễ dàng hơn bao giờ hết.
  • Auth0 cung cấp các tính năng mạnh mẽ cho việc quản lý người dùng, đăng nhập và phân quyền.
  • Dễ dàng tích hợp các phương thức xác thực phổ biến như OAuth, OpenID Connect và JWT (JSON Web Tokens) vào ứng dụng mà không cần phải xây dựng lại từ đầu.

Sơ đồ chức năng Auth0

Sơ đồ chức năng Auth0

II. Bảo mật Nest.js bằng Auth0 và quản lý danh tính người dùng

1. Cài đặt, cấu hình API Auth0

Sau khi tạo tài khoản Auth0, hãy đăng nhập vào tài khoản đó và đi tới phần Auth management Dashboard  của bạn và chọn APIs từ menu Applications nằm bên trái màn hình.

Ở đây sẽ hiển thị cho bạn danh sách API nếu bạn đã tạo bất kỳ API nào cho tài khoản của mình, nhưng đối với hướng dẫn này, hãy tiếp tục và nhấp vào nút TẠO API và thiết lập một API mới. Tiếp theo, cung cấp một tên thân thiện mà bạn cho là phù hợp với API của mình. Đặt identifier là `http://localhost:3010/api` . Điều này sẽ được sử dụng làm đối tượng sau này khi định cấu hình mã thông báo truy cập. Khi bạn đã hoàn tất, hãy để lại thuật toán ký là RS256, vì đây là tùy chọn tốt nhất theo quan điểm bảo mật và nhấp vào nút TẠO để tiếp tục:

Sau khi tạo xong API, các bạn vào lại menu Applications và chọn applications, lúc này Auht0 cũng đã tạo sẵn cho các bạn 1 application cùng tên với API bạn đã tạo và kèm với chữ  Test Application phía sau ( ví dụ trên sẽ tạo ra application là  "nest-api (Test Application)" ). Bạn sẽ tạo một ứng dụng mới đại diện cho ứng dụng React giao diện người dùng trong phần tiếp theo của series.

Tiếp đó, chọn ứng dụng thử nghiệm đã được tạo. Sau đó, bạn sẽ nhấp vào tab "Settings". Bây giờ hãy xác định các trường URL callback được phép thêm http://localhost:3000 làm giá trị. Điều này sẽ hữu ích trong phần tiếp theo của series này. Bây giờ bạn có thể lưu các thay đổi để tiếp tục. Đừng quên sao chép Domain, Client ID, and Client Secret để cài đặt trong source API của bạn.

Dưới đây là full cài đặt Auth0 application của mình:

2. Cài đặt Nest.js authentication middleware

Sau khi setting xong phần Auth0, thì tiếp đến mình sẽ hướng dẫn các bạn làm sau để sử dụng Auth0 để xác thực API của mình.

Bước đầu tiên, các bạn cần tạo 1 middleware để đảm bảo xác thực, chặn những request không hợp lệ đến API của bạn trước khi truy cập tài nguyên của bạn. Cách thức hoạt động như sau: một khi người dùng đã được xác thực bởi Auth0, một mã thông báo truy cập sẽ được tạo ra để cho phép người dùng này sau đó thực hiện việc call API. Để xác minh mã JWT được tạo ra bởi Auth0, bạn sẽ sử dụng middleware Express được cung cấp bởi express-jwt.

Vào thư mục dự án API của bạn, tiến hành cài đặt thư viện cần thiết:  

npm install express-jwt jwks-rsa dotenv

Trong danh sách thư viện ở trên, có một module dotenv dùng để tải biến từ một tệp .env.

Để dễ dàng truy cập và tham khảo các thông tin như Tên miền cho ứng dụng của bạn trên Auth0, hãy tạo một tệp .env trong thư mục gốc của ứng dụng của bạn và dán nội dung sau vào đó:

AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
AUTH0_AUDIENCE=http://localhost:3000/api


Thay thế YOUR_AUTH0_DOMAIN bằng thông tin mà bạn đã nhận được từ bảng điều khiển Auth0 của bạn.

Để cấu hình middleware xác thực, hãy tạo một thư mục có tên common trong thư mục src. Sau đó, tạo một tệp mới có tên authentication.middleware.ts trong thư mục đó. Dán nội dung sau vào tệp mới tạo:

// blog-backend/src/common/authentication.middleware.ts
    
import { Injectable, NestMiddleware } from '@nestjs/common';
import * as jwt from 'express-jwt';
import { expressJwtSecret } from 'jwks-rsa';
import { Request, Response } from 'express';
import * as dotenv from 'dotenv';
dotenv.config();
    
@Injectable()
export class AuthenticationMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: Function) {
    jwt({
        secret: expressJwtSecret({
          cache: true,
          rateLimit: true,
          jwksRequestsPerMinute: 5,
          jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`,
        }),
        issuer: `https://${process.env.AUTH0_DOMAIN}/`,
        algorithms: ['RS256'],
      })(req, res, (err) => {
        if (err) {
          const status = err.status || 500;
          const message = err.message || 'Sorry we were unable to process your request.';
          return res.status(status).send({
            message,
          });
        }
        next();
      });
  }
}

Mã này sẽ kiểm tra xem  Access token  trong một request API có hợp lệ hay không. Nếu mã thông báo không hợp lệ, người dùng sẽ nhận được một thông báo cho biết rằng mã thông báo xác thực không hợp lệ.

Sau đó, trở lại file article.module.ts và cập nhật file như được hiển thị dưới đây:

...
export class ArticleModule implements NestModule {
    configure(consumer: MiddlewareConsumer): MiddlewareConsumer | void {
      consumer.apply(AuthenticationMiddleware).forRoutes(
        { method: RequestMethod.POST, path: '/blog/post' },
        { method: RequestMethod.PUT, path: '/blog/edit' },
        { method: RequestMethod.DELETE, path: '/blog/delete' }
      )
    }
}

Với việc triển khai này, bất kỳ yêu cầu sau đó không có Access Token đối với các tuyến đường sau sẽ không được ứng dụng chấp nhận:

  • PUT /articles/post
  • GET /articles/edit
  • DELETE /articles/delete

Để kiểm tra điều này, hãy bắt đầu ứng dụng và sử dụng lệnh npm run start:dev. Sau đó, hãy thử gửi một yêu cầu POST đến http://localhost:3010/articles/post từ Postman. Bạn sẽ thấy phản hồi như được miêu tả trong hình ảnh dưới đây:

Trong phần tiếp theo của series này, bạn sẽ có cơ hội tạo một access token ngay sau khi xác thực bởi Auth0. Nhưng như một bằng chứng thực nghiệm, hiện tại, bạn có thể lấy một mã thông báo truy cập thử nghiệm cho API của bạn từ bảng điều khiển quản lý tài khoản Auth0. Truy cập phần API trong bảng điều khiển Auth0 của bạn và nhấp vào API đã được tạo trước đó.

Bây giờ, hãy nhấp vào tab "Test" và cuộn xuống để sao chép Mã thông báo Truy cập được hiển thị dưới tiêu đề "Response".
Tiếp theo, mở ứng dụng Postman và từ tab "Authorization", chọn "Bearer Token" và dán Mã thông báo Truy cập của bạn vào đây:

3. Test tất cả các enpoint đã được cài đặt

Sử dụng Postman và access token bạn đã nhận được, bạn có thể thử gửi các yêu cầu này để kiểm tra xem ứng dụng có cho phép truy cập vào các tài nguyên này hay không.

III. Tổng kết

Trong hướng dẫn này, bạn đã thành công xây dựng một API bằng Nest.js và đã tiến xa hơn để bảo vệ một sốenpoint với ứng dụng bằng cách đảm bảo và xác minh JWT (JSON Web Token) được phát bởi Auth0.

Đây là phần hai của loạt bài này, và tiếp đến là phần thứ ba, bạn sẽ thiết lập giao diện người dùng và logic Frontend bằng React và TypeScript.

* Về Auth0

Auth0 by Okta tiếp cận hiện đại đối với danh tính khách hàng và cho phép các tổ chức cung cấp quyền truy cập an toàn vào bất kỳ ứng dụng nào, cho bất kỳ người dùng nào. Auth0 là một nền tảng có khả năng tùy chỉnh cao, đơn giản và linh hoạt khi cần. Bảo vệ hàng tỷ lượt đăng nhập mỗi tháng, Auth0 mang lại sự tiện lợi, bảo mật và riêng tư để khách hàng có thể tập trung vào sáng tạo mà không cần quan tâm đến bảo mật người dùng. Để biết thêm thông tin, hãy truy cập https://auth0.com.