> ## Documentation Index
> Fetch the complete documentation index at: https://docs.econtractid.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Xác thực & Phân quyền API

> Hướng dẫn xác thực JWT và phân quyền khi tích hợp econtractid API

## Xác thực (Authentication)

econtractid API sử dụng **JWT Bearer Token** để xác thực mọi request.

### Lấy Access Token

```bash theme={null}
POST /api/auth/login
Content-Type: application/json

{
  "username": "user@example.com",
  "password": "your_password"
}
```

**Response:**

```json theme={null}
{
  "statusCode": 200,
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIs...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIs...",
    "expiresIn": 3600
  }
}
```

### Sử dụng Token trong request

Thêm header `Authorization` vào mỗi API call:

```bash theme={null}
GET /api/contracts
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
```

***

## Làm mới Token (Refresh Token)

Access Token có hiệu lực **1 giờ**. Khi hết hạn, dùng Refresh Token để lấy cặp token mới:

```bash theme={null}
POST /api/auth/refresh
Content-Type: application/json

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}
```

**Response:** Trả về cặp `accessToken` + `refreshToken` mới.

<Warning>
  Refresh Token có hiệu lực **7 ngày** và chỉ dùng được **một lần**. Sau khi dùng, token cũ bị vô hiệu hoá (Refresh Token Rotation).
</Warning>

***

## Luồng xác thực đầy đủ

```
Client              econtractid API
  │                       │
  │─── POST /auth/login ──►│
  │◄── accessToken ────────│
  │◄── refreshToken ───────│
  │                       │
  │─── GET /contracts ────►│ (Authorization: Bearer accessToken)
  │◄── data ───────────────│
  │                       │
  │  ... 1 giờ sau ...    │
  │                       │
  │─── GET /contracts ────►│ ⟵ 401 Unauthorized (token hết hạn)
  │                       │
  │─── POST /auth/refresh ►│ (refreshToken)
  │◄── new accessToken ────│
  │◄── new refreshToken ───│
  │                       │
  │─── GET /contracts ────►│ (new accessToken)
  │◄── data ───────────────│
```

***

## Phân quyền (Authorization)

Mỗi API endpoint được bảo vệ bởi một hoặc nhiều **permission**.

### Cấu trúc Permission

```
resource:action
```

Ví dụ:

* `contract:create` — tạo hợp đồng
* `contract:view-all` — xem tất cả hợp đồng
* `user:manage` — quản lý người dùng

### Lỗi phân quyền

```json theme={null}
{
  "statusCode": 403,
  "message": "Forbidden: insufficient permissions",
  "error": "Forbidden"
}
```

***

## Xử lý lỗi

| Status Code | Ý nghĩa                                   |
| ----------- | ----------------------------------------- |
| `200`       | Thành công                                |
| `201`       | Tạo mới thành công                        |
| `400`       | Dữ liệu đầu vào không hợp lệ              |
| `401`       | Chưa xác thực hoặc token hết hạn          |
| `403`       | Không đủ quyền hạn                        |
| `404`       | Không tìm thấy tài nguyên                 |
| `422`       | Lỗi nghiệp vụ (validation business logic) |
| `500`       | Lỗi server                                |

### Cấu trúc response lỗi chuẩn

```json theme={null}
{
  "statusCode": 400,
  "message": "Email đã tồn tại trong hệ thống",
  "error": "Bad Request",
  "details": {
    "field": "email",
    "code": "EMAIL_ALREADY_EXISTS"
  }
}
```

***

## API Key (cho tích hợp server-to-server)

Với các tích hợp backend không cần user context, dùng **API Key**:

```bash theme={null}
GET /api/contracts
X-API-Key: eck_live_xxxxxxxxxxxxxxxxxxxx
```

Tạo API Key tại: **Cài đặt** → **Tích hợp** → **API Keys**.

<Tip>
  API Key nên được lưu trong **biến môi trường** (`.env`), không hardcode trong source code.
</Tip>
