Commit a831d8f6 authored by Vy Nguyễn Minh Khang's avatar Vy Nguyễn Minh Khang

Merge branch 'fix/session-page' into 'develop'

fix(session-pages): avoid both project use one session

See merge request !4
parents 73f98745 00dbe5a0
# SSO VietProDev Backend # SSO VietProDev Backend
Production-ready SSO Authorization Server built with TypeScript, Express.js, and Sequelize — supports **OIDC/OAuth2**, **bcryptjs**, **PostgreSQL**, **MongoDB audit logs**, and **Redis**. > Production-ready **OIDC/OAuth2 Authorization Server** + **REST API** built with TypeScript, Express, and Sequelize.
> Supports PostgreSQL, MongoDB audit logging, Redis, and email verification.
## Quick Start [![Node](https://img.shields.io/badge/Node-%E2%89%A520-339933)](https://nodejs.org)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178C6)](https://www.typescriptlang.org)
[![License](https://img.shields.io/badge/License-ISC-blue)](./LICENSE)
---
## Table of Contents
1. [Overview](#1-overview)
2. [Tech Stack](#2-tech-stack)
3. [Quick Start](#3-quick-start)
4. [Project Structure](#4-project-structure)
5. [Environment Variables](#5-environment-variables)
6. [OIDC Flow](#6-oidc-flow)
7. [REST API](#7-rest-api)
8. [Architecture](#8-architecture)
9. [Available Scripts](#9-available-scripts)
10. [Documentation](#10-documentation)
---
## 1. Overview
`SSO VietProDev Backend` là một **OIDC Authorization Server** đầy đủ tính năng, cung cấp:
- **OIDC/OAuth2** — Authorization Code, Client Credentials, Refresh Token, RP-Initiated Logout
- **REST API** — Auth, Users, Roles, Permissions, Files, Notifications, Audit
- **Email Verification** — User mới phải verify email trước khi login
- **Custom UI** — Login, Register, Consent, Logout pages (Handlebars)
- **Audit Logging** — MongoDB-backed outbox pattern
- **Rate Limiting** — Redis-backed
- **OpenAPI 3.0** — Auto-generated từ Zod schemas
| Service | URL |
|---------|-----|
| **SSO Backend** | `http://localhost:3001` |
| **Swagger UI** | `http://localhost:3001/swagger/index` |
| **OIDC Discovery** | `http://localhost:3001/.well-known/openid-configuration` |
| **JWKS** | `http://localhost:3001/oauth/jwks` |
| **Health Check** | `http://localhost:3001/health` |
---
## 2. Tech Stack
| Layer | Technology |
|-------|-----------|
| Runtime | Node.js >= 20 + TypeScript 5 (ESM, NodeNext) |
| Framework | Express.js + `express-automatic-routes` |
| ORM | Sequelize (PostgreSQL) |
| Auth Core | `oidc-provider` v9 + JWT |
| Validation | Zod (config) + Joi (request) |
| Audit | MongoDB (outbox pattern) |
| Cache / Queue | Redis + BullMQ |
| Password | bcryptjs |
| Email | Nodemailer (SMTP) + dev fallback |
| File Storage | MinIO (S3-compatible) |
| API Docs | OpenAPI 3.0 (`@asteasolutions/zod-to-openapi`) |
| Testing | Jest + Supertest |
---
## 3. Quick Start
### Prerequisites
- Node.js >= 20.x
- pnpm >= 10.x
- Docker Desktop (for Postgres, Redis, MongoDB, MinIO)
- PostgreSQL 17 (local hoặc Docker)
### Setup
```bash ```bash
# 1. Install dependencies
pnpm install pnpm install
cp .env.example .env # fill in DB, Redis, JWT, OIDC, MongoDB values
docker compose up -d # start PostgreSQL, MongoDB, Redis, MinIO # 2. Copy env file - Không cần run cái này này
pnpm migrate # run SQL migrations (001-036) cp .env.example .env
pnpm dev # start development server
# 3. Start infrastructure (Redis, MongoDB, MinIO — Postgres dùng local)
docker compose up -d mongo redis minio
# 4. Run migrations + seeds
pnpm db:setup
# 5. Start dev server
pnpm run dev
``` ```
**Server**: `http://localhost:3001` ### Default accounts (sau `pnpm db:setup`)
**Swagger UI**: `http://localhost:3001/swagger/index`
**OIDC Discovery**: `http://localhost:3001/.well-known/openid-configuration` ```
System Admin: admin@vietprodev.com / VietPro@2026
Admin: admin@sso.vietprodev.com / VietPro@2026
User: user@sso.vietprodev.com / VietPro@2026
```
### Default OIDC clients
| Client ID | Redirect URI | Secret |
|-----------|-------------|--------|
| `project-a-demo` | `http://localhost:4001/auth/callback` | `project-a-demo-secret-123456` |
| `project-b-demo` | `http://localhost:4002/auth/callback` | `project-b-demo-secret-654321` |
--- ---
## Architecture ## 4. Project Structure
``` ```
Browser/App sso-vietprodev-backend/
├── src/
├─ REST API (JWT) ──── Express Backend │ ├── config/ # Env config (Zod-validated, layered)
│ └─ /api/v1/* (auto-routed controllers) │ ├── constants/ # Error codes, roles, enums
│ ├── contracts/ # Zod schemas + OpenAPI paths
└─ OIDC Flow ────────── oidc-provider │ ├── controllers/ # Express handlers (api/v1, admin)
├─ /.well-known/openid-configuration │ ├── interfaces/ # Shared TypeScript types
├─ /oauth/authorize │ ├── middlewares/ # Auth, validation, rate-limit, response
├─ /oauth/token │ ├── models/ # Sequelize models (33 SSO models)
├─ /oauth/userinfo │ ├── providers/ # Data access layer (31 SSO providers)
├─ /oauth/logout │ ├── services/ # Business logic
└─ /oidc/interaction/* (login, register, consent) │ ├── oidc/ # OIDC provider, adapter, views
│ ├── utils/ # Logger, helpers
PostgreSQL ── users, roles, permissions, sessions, clients, oidc_grants │ ├── workers/ # Background workers (audit, etc.)
MongoDB ───── audit_logs │ ├── server.ts # Express bootstrap
Redis ─────── rate limiting, caching, sessions │ └── index.ts # Entry point
├── sql/
│ ├── migrations/ # 13 SSO migrations (001-040)
│ ├── seeds/ # Default roles, users, clients
│ ├── scripts/ # migrate.js, check-db.js
│ └── clean-migration.sql # Consolidated single-file migration
├── tests/
│ ├── unit/ # Unit tests
│ └── integration/ # Integration tests
├── storage/
│ └── swagger/ # Generated OpenAPI spec
├── docker-compose.yml
├── .env.example
└── package.json
``` ```
## Stack ---
| Layer | Technology | ## 5. Environment Variables
|---|---|
| Runtime | Node.js 20 + TypeScript | File `.env` chứa 17 sections. Quan trọng nhất:
| Framework | Express.js + express-automatic-routes |
| ORM | Sequelize (PostgreSQL) | ```bash
| Auth | OIDC/OAuth2 (oidc-provider) + JWT | # Server
| Password | bcryptjs | PORT=3001
| Audit | MongoDB | NODE_ENV=development
| Cache | Redis | BACKEND_URL=http://localhost:3001
| Docs | OpenAPI 3.0 (Zod + zod-to-openapi) |
# PostgreSQL (local)
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your-password
DB_NAME=vietprodev_sso
# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
# MongoDB (audit)
MONGO_URI=mongodb://localhost:27017/sso_audit
# OIDC
OIDC_ISSUER=http://localhost:3001
OIDC_COOKIE_KEYS=key1,key2,key3
# Email (SMTP)
EMAIL_HOST=smtp.example.com # Đổi sang SMTP thật để gửi email
EMAIL_PORT=587
EMAIL_USER=noreply@vietprodev.com
EMAIL_PASS=app-password
EMAIL_FROM=noreply@vietprodev.com
EMAIL_VERIFICATION_TTL_HOURS=24
```
> **Dev mode**: Khi `EMAIL_HOST=smtp.example.com` (placeholder), email tự động ghi vào `dev-mail.log` thay vì gửi thật.
> **Production checklist**: `BACKEND_URL`, `DB_*`, `OIDC_COOKIE_KEYS`, `JWT_SECRET`, `TOKEN_ENCRYPTION_KEY` (min 32 chars), `ADMIN_API_KEY` (min 32 chars), real SMTP credentials.
Xem chi tiết: [docs/backend/configuration.md](./docs/backend/configuration.md)
--- ---
## Important Notes ## 6. OIDC Flow
**Database Schema Changes**: NEVER modify database structure directly. Always use migration files in `sql/migrations/`. ### Endpoints
| Endpoint | Method | Auth | Description |
|----------|--------|------|-------------|
| `/.well-known/openid-configuration` | GET | — | OIDC Discovery |
| `/oauth/jwks` | GET | — | Public JWKS |
| `/oauth/authorize` | GET/POST | — | Authorization endpoint |
| `/oauth/token` | POST | `client_secret` | Token exchange |
| `/oauth/userinfo` | GET | Bearer | User claims |
| `/oauth/introspect` | POST | `client_secret` | Token introspection |
| `/oauth/revoke` | POST | `client_secret` | Token revocation |
| `/oauth/logout` | GET/POST | — | RP-Initiated Logout |
| `/oidc/interaction/:uid` | GET | — | Login/Register/Consent page |
| `/oidc/interaction/:uid/login` | POST | — | Submit login |
| `/oidc/interaction/:uid/register` | POST | — | Submit registration |
| `/oidc/interaction/:uid/confirm` | POST | — | Approve consent |
| `/oidc/interaction/:uid/cancel` | POST | — | Cancel consent |
| `/oidc/interaction/:uid/resend-verification` | POST | — | Resend email verification |
| `/oidc/interaction/:uid/abort` | POST | — | Abort interaction |
### Authorization Code Flow
```sql ```
REVOKE CREATE ON SCHEMA public FROM app_user; 1. User click "Login with SSO" trên client app
REVOKE ALTER ON ALL TABLES IN SCHEMA public FROM app_user; → redirect: GET /oauth/authorize?client_id=...&response_type=code&...
2. SSO render login page: GET /oidc/interaction/:uid
3. User nhập credentials
→ POST /oidc/interaction/:uid/login
4. SSO render consent page (lần đầu)
→ GET /oidc/interaction/:uid
5. User approve
→ POST /oidc/interaction/:uid/confirm
6. SSO redirect về client với code
→ GET {redirect_uri}?code=XXX&state=YYY
7. Client exchange code lấy tokens
→ POST /oauth/token (client_secret_basic)
8. Client fetch user info
→ GET /oauth/userinfo (Bearer access_token)
``` ```
--- ---
## Important Commands ## 7. REST API
### Authentication
| Method | Endpoint | Auth | Description |
|--------|----------|------|-------------|
| POST | `/api/v1/auth/register` | — | Tạo tài khoản (gửi email verification) |
| GET | `/api/v1/auth/verify-email` | — | Xác thực email từ token |
| POST | `/api/v1/auth/resend-verification` | — | Gửi lại email verification |
| POST | `/api/v1/auth/login` | — | Login (web/mobile) |
| POST | `/api/v1/auth/refresh` | — | Refresh access token |
| POST | `/api/v1/auth/logout` | Bearer | Logout |
| GET | `/api/v1/auth/me` | Bearer | User hiện tại |
| POST | `/api/v1/auth/forgot-password/*` | — | Quên mật khẩu |
### Resources (cần Bearer token)
- **Users**`/api/v1/users`
- **Roles**`/api/v1/roles`
- **Permissions**`/api/v1/permissions`
- **User Roles**`/api/v1/user-roles`
- **Role Permissions**`/api/v1/role-permissions`
- **Files**`/api/v1/files`
- **Notifications**`/api/v1/notifications`
- **Audit Logs**`/api/v1/audit-logs`
Xem đầy đủ: Swagger UI tại `http://localhost:3001/swagger/index`
---
## 8. Architecture
```
┌─────────────────────────────────────────────────────────┐
│ Browser / Client Apps │
└────────────┬────────────────────────────┬───────────────┘
│ │
REST API │ │ OIDC Flow
(Bearer) │ │ (Auth Code)
▼ ▼
┌─────────────────────────────────────────────────────────┐
│ SSO Backend (Express + oidc-provider) │
│ ┌────────────────┐ ┌──────────────────────────────┐ │
│ │ /api/v1/* │ │ /oauth/* + /oidc/interaction│ │
│ │ Controllers │ │ OIDC Provider + Custom UI │ │
│ └────────┬───────┘ └──────────┬───────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Services (Auth, Email, Notification, Audit...) │ │
│ └──────────────────┬───────────────────────────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Providers (Sequelize data access) │ │
│ └──────────────────┬───────────────────────────────┘ │
└─────────────────────┼───────────────────────────────────┘
┌─────────────┼─────────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Postgres│ │ MongoDB │ │ Redis │
│ (SSO │ │ (audit │ │ (cache, │
│ data) │ │ logs) │ │ rate) │
└─────────┘ └─────────┘ └─────────┘
```
### Request Flow
```
HTTP Request
→ Middleware (auth, validation, rate-limit)
→ Controller (parse, format)
→ Service (business logic)
→ Provider (data access)
→ Model → PostgreSQL
```
### Layered Architecture
| Layer | Folder | Responsibility |
|-------|--------|---------------|
| Controller | `src/controllers/` | HTTP handling, thin — delegate to Services |
| Service | `src/services/` | Business logic, orchestration |
| Provider | `src/providers/` | Data access over Sequelize |
| Model | `src/models/` | Sequelize definitions |
| Middleware | `src/middlewares/` | Auth, validation, rate-limit |
| Contract | `src/contracts/` | Zod schemas + OpenAPI paths |
| Template | `src/oidc/views/` | Handlebars UI templates |
| Constant | `src/constants/` | Error codes, roles, enums |
| Config | `src/config/` | Zod-validated env config |
---
## 9. Available Scripts
### Development ### Development
| Command | Description | | Command | Description |
|---|---| |---------|-------------|
| `pnpm dev` / `pnpm start:dev` | Run development server with hot reload | | `pnpm dev` | Dev server với hot reload |
| `pnpm build` | Build for production | | `pnpm start:dev` | Kill port 3001 + restart dev server |
| `pnpm start` | Run production server | | `pnpm build` | Build TypeScript → `dist/` |
| `pnpm docker:dev` | Run with Docker Compose (full stack) | | `pnpm start` | Chạy production build |
### Database ### Database
| Command | Description | | Command | Description |
|---|---| |---------|-------------|
| `pnpm migrate` | Run SQL migrations | | `pnpm migrate` | Apply SQL migrations |
| `pnpm seed` | Seed default data | | `pnpm seed` | Apply seeds |
| `pnpm db:setup` | Run migrations + seeds | | `pnpm db:setup` | migrate + seed |
| `pnpm gen-db` | Generate models from database | | `pnpm check-db` | Verify database state |
| `pnpm gen-db` | Generate models từ database |
### Quality ### Code Quality
| Command | Description | | Command | Description |
|---|---| |---------|-------------|
| `pnpm type-check` | `tsc --noEmit` |
| `pnpm lint` | ESLint check | | `pnpm lint` | ESLint check |
| `pnpm type-check` | TypeScript check | | `pnpm lint:fix` | ESLint auto-fix |
| `pnpm format` | Prettier write |
| `pnpm quality:check` | lint + type-check + swagger + coverage | | `pnpm quality:check` | lint + type-check + swagger + coverage |
| `pnpm swagger:validate` | Generate then validate Swagger spec |
### Swagger / OpenAPI
| Command | Description |
|---------|-------------|
| `pnpm swagger:generate` | Generate OpenAPI spec |
| `pnpm swagger:validate` | Generate + validate |
| `pnpm swagger:diff` | Diff vs baseline (CI) |
### Testing ### Testing
| Command | Description | | Command | Description |
|---|---| |---------|-------------|
| `pnpm test` | Run all tests |
| `pnpm test:unit` | Unit tests only | | `pnpm test:unit` | Unit tests only |
| `pnpm test:integration` | Integration tests only | | `pnpm test:integration` | Integration tests only |
| `pnpm test:coverage` | Full suite + coverage report | | `pnpm test:coverage` | Tests + coverage report |
| `pnpm test:critical` | Critical gate — auth + security | | `pnpm test:critical` | Critical gate — auth + security |
--- ### Docker
## OIDC Endpoints | Command | Description |
|---------|-------------|
| Endpoint | Description | | `pnpm docker:dev:detach` | Full stack (app + infra) detached |
|---|---| | `pnpm docker:stop` | Stop all containers |
| `GET /.well-known/openid-configuration` | OIDC Discovery document | | `pnpm docker:logs:dev` | Tail dev app logs |
| `GET /oauth/authorize` | Authorization endpoint |
| `POST /oauth/token` | Token endpoint | ### CI/CD
| `GET /oauth/userinfo` | UserInfo endpoint |
| `GET /oauth/jwks` | JWKS endpoint | | Command | Description |
| `POST /oauth/revoke` | Token revocation | |---------|-------------|
| `POST /oauth/introspect` | Token introspection | | `pnpm ci:check` | type-check + lint + structure + security + coverage |
| `GET /oidc/interaction/:uid` | Login page | | `pnpm ci:quality` | type-check + lint + structure + swagger |
| `POST /oidc/interaction/:uid/login` | Submit login | | `pnpm ci:security` | Full security audit |
| `POST /oidc/interaction/:uid/register` | Register account | | `pnpm ci:test` | Test suite cho CI |
| `POST /oidc/interaction/:uid/confirm` | Approve consent |
| `POST /oidc/interaction/:uid/cancel` | Cancel consent |
--- ---
## Docs ## 10. Documentation
| Topic | Link | | Topic | Link |
|---|---| |-------|------|
| Setup & Environment | [docs/setup.md](docs/setup.md) | | Setup & Environment | [docs/backend/setup.md](./docs/backend/setup.md) |
| New API Development | [docs/api-development.md](docs/api-development.md) | | Configuration | [docs/backend/configuration.md](./docs/backend/configuration.md) |
| Error Handling | [docs/error-handling.md](docs/error-handling.md) | | Architecture | [docs/backend/architecture.md](./docs/backend/architecture.md) |
| Configuration | [docs/configuration.md](docs/configuration.md) | | Coding Conventions | [docs/backend/conventions.md](./docs/backend/conventions.md) |
| Swagger / OpenAPI | [docs/swagger.md](docs/swagger.md) | | Security | [docs/backend/security.md](./docs/backend/security.md) |
| Architecture | [docs/architecture.md](docs/architecture.md) | | API Response Guide | [guidelines/API_RESPONSE_GUIDE.md](./guidelines/API_RESPONSE_GUIDE.md) |
| Testing | [docs/testing.md](docs/testing.md) | | Authentication Guide | [guidelines/AUTHENTICATION_GUIDE.md](./guidelines/AUTHENTICATION_GUIDE.md) |
| Conventions | [docs/conventions.md](docs/conventions.md) | | Validation Guide | [guidelines/VALIDATION_GUIDE.md](./guidelines/VALIDATION_GUIDE.md) |
| Security | [docs/security.md](docs/security.md) | | Query Modifier | [guidelines/QUERY_MODIFIER_GUIDE.md](./guidelines/QUERY_MODIFIER_GUIDE.md) |
| API Generator | [guidelines/API_GENERATOR_GUIDE.md](./guidelines/API_GENERATOR_GUIDE.md) |
| Coding Convention | [guidelines/CODING_CONVENTION.md](./guidelines/CODING_CONVENTION.md) |
| VietProDev Guidelines | [guidelines/VIETPRODEV_GUIDELINES.md](./guidelines/VIETPRODEV_GUIDELINES.md) |
| Developer Guide | [RUN.md](./RUN.md) |
---
## License
ISC © VietProDev Team
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment