# Lesson 6 - Authentication-Authorization

Authentication (Xác thực) và Authorization (Phân quyền) là hai khái niệm quan trọng trong bảo mật thông tin và quản lý quyền truy cập, nhất là đối với lập trình server. Ta sẽ cùng tìm hiểu lần lượt về hai khái niệm này.

## Authentication (Xác thực)

**1. Khái niệm Authentication**

* **Authentication** là quá trình xác minh danh tính của một người dùng hoặc một thực thể khi truy cập vào hệ thống, ứng dụng hoặc dịch vụ.
* Authentication đảm bảo rằng người dùng là người thật sự và có quyền truy cập vào hệ thống.

**2. Lý do tại sao cần Authentication**

* **Bảo mật**: Authentication đảm bảo tính riêng tư và bảo mật. Nó ngăn chặn người không được ủy quyền truy cập vào thông tin cá nhân hoặc dịch vụ của người khác.
* **Ngăn chặn lừa đảo**: Ngăn chặn việc người khác sử dụng danh tính của người dùng một cách trái phép hoặc lừa đảo.

**3. Ví dụ thực tế về Authentication**

* **Hệ thống ngân hàng**: Khi bạn truy cập vào tài khoản ngân hàng trực tuyến, bạn phải xác thực danh tính bằng cách nhập mật khẩu hoặc sử dụng xác thực đa yếu tố (OTP) trước khi truy cập vào tài khoản của mình.
* **Mạng xã hội**: Để truy cập vào tài khoản mạng xã hội của bạn, bạn phải đăng nhập bằng tên người dùng và mật khẩu.

**4. Triển khai với server express**

&#x20;Ví dụ:

```javascript
import express from 'express';
const app = express();

// Middleware để xác thực người dùng
app.use((req, res, next) => {
  const isAuthenticated = true; // Kiểm tra xem người dùng đã được xác thực hay chưa
  if (isAuthenticated) {
    // Người dùng đã được xác thực, cho phép truy cập
    next();
  } else {
    res.status(401).send('Unauthorized'); // Trả về lỗi 401 nếu không được xác thực
  }
});

app.get('/', (req, res) => {
  res.send('Welcome to the secure area!');
});

app.listen(8080, () => {
  console.log('Server is running on port 8080');
});
```

Trong thực tế, Authentication thường được sử dụng để bảo vệ các chức năng và tài nguyên quan trọng trong ứng dụng hoặc hệ thống khi một người dùng muốn truy cập vào các dịch vụ được cung cấp bởi server, điển hình là chức năng đăng nhập, nhằm xác thực người dùng có thể truy cập vào hệ thống này.

Nhưng sau khi đăng nhập xong, làm thế nào để server có thể biết được với các request tiếp theo, họ sẽ thông báo cho server biết rằng họ đã đăng nhập và server đã xác thực họ thành công.

Điều này ta sẽ có nhiều cách, ví dụ như đoạn code phía trên, isAuthenticated được hard code trực tiếp trong logic này, vậy nếu triển khai với client, sau khi kiểm tra xác thực người dùng xong, server sẽ trả về một thông tin cho client `isAuthenticated = true` và mỗi request client gửi lên, chỉ cần đính kèm trường isAuthenticated này lên là đã có thể xác thực xong.

Tuy nhiên, việc làm này sẽ rất rủi ro, vì hoàn toàn có thể tự khai báo trường `isAuthenticated = true` trong mỗi request gửi lên. Dĩ nhiên, ngoài cách này ra, ta sẽ kiểm tra thông tin người dùng trong mỗi request lên hoàn toàn có thể chấp nhận được, nhưng sẽ không khả thi, vì mỗi lần cần dùng các API nào đó, người dùng lại phải gửi lên thông tin đăng nhập để xác thực.

Cách làm khác và được sử dụng rộng rãi nhất, ta sẽ sử dụng một dạng được ví như là *chữ ký*, để cho server kiểm tra trong mỗi request, còn được gọi là token, mọi kiến thức về token, ta sẽ được tìm hiểu trong bài sau.

## Authorization (Phân quyền)

**1. Khái niệm Authorization**

* **Authorization** là quá trình xác định và kiểm tra quyền truy cập của người dùng sau khi họ đã được xác thực (authenticated).
* Authorization đảm bảo rằng người dùng chỉ có quyền truy cập vào những tài nguyên hoặc tính năng mà họ được ủy quyền.

**2. Lý do tại sao cần Authorization**

* **Kiểm soát quyền truy cập**: Authorization giúp kiểm soát quyền truy cập và đảm bảo rằng người dùng chỉ có quyền truy cập vào những gì họ cần và được phép sử dụng.
* **Bảo vệ tài nguyên và thông tin**: Nó đảm bảo rằng người dùng không thể truy cập vào các tài nguyên nhạy cảm hoặc thông tin quan trọng mà họ không được phép truy cập.

**3. Ví dụ thực tế về Authorization**

* **Hệ thống quản lý tệp**: Trong một hệ thống quản lý tệp, người dùng có thể có quyền truy cập vào tệp và thư mục cụ thể dựa trên vai trò của họ. Ví dụ, người dùng thông thường không thể truy cập vào thư mục quản lý của hệ thống.
* **Ứng dụng di động**: Trong ứng dụng di động, người dùng có thể chỉnh sửa hồ sơ cá nhân của họ, nhưng không thể chỉnh sửa hồ sơ của người khác

**4. Triển khai với server express**

```javascript
import express from 'express';
const app = express();

// Middleware để kiểm tra quyền truy cập
app.use((req, res, next) => {
  const userRole = 'admin'; // Vai trò của người dùng (ví dụ: admin hoặc user)
  if (userRole === 'admin') {
    next(); // Cho phép truy cập vào route
  } else {
    res.status(403).send('Forbidden'); // Trả về lỗi 403 nếu không có quyền truy cập
  }
});

app.get('/admin', (req, res) => {
  res.send('Admin panel'); // Route chỉ có quyền truy cập cho admin
});

app.listen(8080, () => {
  console.log('Server is running on port 8080');
});
```

Tương tự với Authentication, logic phía trên, mới chỉ đang ở dạng demo, còn thực tế ta sẽ không được phép làm như trên, vì xét về tính bảo mật, hoàn toàn không có. Với trường hợp này, token vẫn sẽ là một lựa chọn được sử dụng nhiều nhất.

## Kết hợp Authentication và Authorization

* **Kết hợp Authentication và Authorization** đảm bảo rằng người dùng chỉ có quyền truy cập vào tài nguyên và tính năng sau khi đã được xác thực và được ủy quyền.
* Đây là một phần quan trọng trong việc xây dựng hệ thống bảo mật và quản lý quyền truy cập hiệu quả.

Các logic này, như có thể thấy ở phía trên, ta sẽ sử dụng chúng như một middleware và apply cho hệ thống dạng global hoặc cho từng các API cần tới, tương lai, ta có thể còn có nhiều middleware khác nữa, vậy việc phân tách logic dành cho middleware thành một module là cần thiết. Thực hiện theo các bước phía dưới:

Tạo thư mục tên là `middlewares` , file `auth.js`

```javascript
const authMiddleware = {
    authentication: (req, res, next) => {
        const isAuthenticated = true; // Kiểm tra xem người dùng đã được xác thực hay chưa
        if (isAuthenticated) {
        // Người dùng đã được xác thực, cho phép truy cập
        next();
      } else {
        res.status(401).send('Unauthorized'); // Trả về lỗi 401 nếu không được xác thực
      }
    },
    auhthorizationAdmin: (req, res, next) => {
        const userRole = 'admin'; // Vai trò của người dùng (ví dụ: admin hoặc user)
        if (userRole === 'admin') {
        next(); // Cho phép truy cập vào route
      } else {
        res.status(403).send('Forbidden'); // Trả về lỗi 403 nếu không có quyền truy cập
      }
    }
};
export default authMiddleware;
```

{% hint style="info" %}
Nên sử dụng với cú pháp của try catch
{% endhint %}

File server index.js

```javascript
import express from 'express';
import authMiddleware from './middlewares/auth.js';
const app = express();

// Middleware để kiểm tra xác thực
app.use(authMiddleware.authentication);

// Kiểm tra quyền truy cập API
app.get('/admin', authMiddleware.auhthorizationAdmin,(req, res) => {
  res.send('Admin panel');
});

app.listen(8080, () => {
  console.log('Server is running on port 8080');
});
```

## Thực hành

Sử dụng kiến thức đã được tìm hiểu, kết hợp với nội dung các bài học trước, thực hiện Authentication và Authorization với các bài liên quan về tạo, chỉnh sửa, xoá bài post, comment, thực hiện tạo tài khoản admin và cho phép toàn quyền truy cập, chỉnh sửa các dữ liệu.

## Kết

Authentication và Authorization là điều không thể thiếu trong bất kỳ ứng dụng nào, giúp cải thiện bảo mật thông tin. Trong nội dung này, ta cũng được nhắc tới token, nhưng tuy nhiên, để triển khai được, ta cần phải hoàn thiện, cũng như tìm hiểu thêm cho kỹ thuật xác thực.
