263 lines
9.2 KiB
Markdown
263 lines
9.2 KiB
Markdown
# SSO Service
|
||
|
||
Self-hosted SSO / OIDC-сервис — аналог Keycloak / Яндекс ID. Node.js (NestJS).
|
||
|
||
## Технологии
|
||
|
||
- **Runtime:** Node.js 22, NestJS 11
|
||
- **Database:** PostgreSQL 16 + Prisma ORM
|
||
- **Cache:** Redis 7
|
||
- **Message Broker:** RabbitMQ 4
|
||
- **Logging:** Pino (JSON, nestjs-pino)
|
||
- **Metrics:** Prometheus
|
||
- **Security:** Argon2, JWT (Access + Refresh), Helmet, OIDC (authorization_code, PKCE)
|
||
- **Templates:** EJS + Bootstrap 5
|
||
|
||
## Возможности
|
||
|
||
### Аутентификация
|
||
- Логин/пароль (Argon2)
|
||
- Вход по коду на email
|
||
- Вход по коду на телефон
|
||
- QR-авторизация (для мобильного приложения)
|
||
- Refresh + rotate токенов
|
||
|
||
### Веб-панель
|
||
- `/login` — страница входа (пароль, код на email, QR)
|
||
- `/register` — регистрация
|
||
- `/profile` — личный кабинет (редактирование профиля)
|
||
- `/admin` — админ-панель:
|
||
- Статистика (пользователи, клиенты, сессии)
|
||
- CRUD пользователей
|
||
- CRUD OAuth-клиентов (как oauth.yandex.ru)
|
||
|
||
### Роли
|
||
- **USER** — только свой профиль
|
||
- **ADMIN** — управление пользователями и OAuth-клиентами
|
||
|
||
### OIDC / OAuth2
|
||
- `/authorize` (authorization_code)
|
||
- `/token` (authorization_code, refresh_token, client_credentials)
|
||
- `/userinfo`
|
||
- `/revoke`
|
||
- PKCE support
|
||
|
||
## Быстрая установка (чистый сервер — всё включено)
|
||
|
||
**Одна команда — установит Node.js 22, Docker, сам сервис и запустит:**
|
||
|
||
```bash
|
||
curl -fsSL https://git.lendry.ru/lendry/sso-service/raw/branch/main/install.sh | bash
|
||
```
|
||
|
||
Скрипт автоматически:
|
||
1. Определяет ОС (Ubuntu/Debian/RHEL/CentOS/Fedora)
|
||
2. Устанавливает **Docker** + **Docker Compose plugin** (если нет)
|
||
3. Устанавливает **Node.js 22 LTS** (через NodeSource или nvm)
|
||
4. Скачивает SSO Service в `~/sso-service`
|
||
5. Генерирует `.env` со случайными JWT-секретами
|
||
6. Запускает PostgreSQL, Redis, RabbitMQ (ждёт готовности)
|
||
7. Устанавливает npm-зависимости, Prisma client, применяет миграции
|
||
8. Сидирует БД (администратор и тестовый OAuth-клиент)
|
||
9. Собирает и запускает сервис (PM2 или background)
|
||
|
||
**Через 2-3 минуты сервис доступен:** http://localhost:3000
|
||
|
||
### Ручная установка (если нужен контроль)
|
||
|
||
```bash
|
||
docker compose up -d
|
||
npx prisma db push
|
||
npx ts-node prisma/seed.ts
|
||
npm run start:dev
|
||
```
|
||
|
||
## API Endpoints
|
||
|
||
| Method | Path | Auth | Description |
|
||
|--------|------|------|-------------|
|
||
| POST | /api/auth/register | No | Регистрация |
|
||
| POST | /api/auth/login | No | Логин (пароль) |
|
||
| POST | /api/auth/login/email-code | No | Логин (код на email) |
|
||
| POST | /api/auth/login/phone-code | No | Логин (код на телефон) |
|
||
| POST | /api/auth/send-email-code | No | Отправить код на email |
|
||
| POST | /api/auth/send-phone-code | No | Отправить код на телефон |
|
||
| POST | /api/auth/qr/init | No | Создать QR-сессию |
|
||
| POST | /api/auth/qr/poll | No | Проверить QR-сессию |
|
||
| POST | /api/auth/refresh | No | Обновить токен |
|
||
| POST | /api/auth/logout | No | Выйти |
|
||
| GET | /api/auth/profile | JWT | Профиль |
|
||
| POST | /api/auth/profile/update | JWT | Обновить профиль |
|
||
| GET | /api/authorize | No | OAuth2 authorize |
|
||
| POST | /api/token | No | OAuth2 token |
|
||
| GET | /api/userinfo | Bearer | OIDC userinfo |
|
||
| POST | /api/revoke | No | Отозвать токен |
|
||
| GET | /api/admin/stats | JWT+ADMIN | Статистика |
|
||
| GET | /api/admin/users | JWT+ADMIN | Список пользователей |
|
||
| POST | /api/admin/users | JWT+ADMIN | Создать пользователя |
|
||
| PUT | /api/admin/users/:id | JWT+ADMIN | Обновить пользователя |
|
||
| DELETE | /api/admin/users/:id | JWT+ADMIN | Удалить пользователя |
|
||
| GET | /api/admin/clients | JWT+ADMIN | Список OAuth-клиентов |
|
||
| POST | /api/admin/clients | JWT+ADMIN | Создать OAuth-клиент |
|
||
| PUT | /api/admin/clients/:id | JWT+ADMIN | Обновить OAuth-клиент |
|
||
| DELETE | /api/admin/clients/:id | JWT+ADMIN | Удалить OAuth-клиент |
|
||
| GET | /metrics | No | Prometheus метрики |
|
||
|
||
## Веб-панель
|
||
|
||
| Страница | URL | Доступ |
|
||
|----------|-----|--------|
|
||
| Логин | /login | Все |
|
||
| Регистрация | /register | Все |
|
||
| Профиль | /profile | Авторизованные |
|
||
| Админка (пользователи) | /admin | ADMIN |
|
||
| Админка (клиенты) | /admin/clients | ADMIN |
|
||
|
||
## Примеры cURL
|
||
|
||
### Регистрация
|
||
```bash
|
||
curl -X POST http://localhost:3000/api/auth/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"email":"user@example.com","password":"secret1234","displayName":"Test"}'
|
||
```
|
||
|
||
### Логин по паролю
|
||
```bash
|
||
curl -X POST http://localhost:3000/api/auth/login \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"email":"user@example.com","password":"secret1234"}'
|
||
```
|
||
|
||
### Логин по коду на email
|
||
```bash
|
||
# Шаг 1: запросить код
|
||
curl -X POST http://localhost:3000/api/auth/send-email-code \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"email":"user@example.com"}'
|
||
|
||
# Шаг 2: войти с кодом
|
||
curl -X POST http://localhost:3000/api/auth/login/email-code \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"email":"user@example.com","code":"123456"}'
|
||
```
|
||
|
||
### QR-авторизация
|
||
```bash
|
||
# Инициализация
|
||
curl -X POST http://localhost:3000/api/auth/qr/init
|
||
|
||
# Проверка статуса
|
||
curl -X POST http://localhost:3000/api/auth/qr/poll \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"sessionId":"<sessionId>"}'
|
||
```
|
||
|
||
### Админка (список пользователей)
|
||
```bash
|
||
curl http://localhost:3000/api/admin/users \
|
||
-H "Authorization: Bearer <admin_token>"
|
||
```
|
||
|
||
### Метрики
|
||
```bash
|
||
curl http://localhost:3000/metrics
|
||
```
|
||
|
||
### RabbitMQ Management
|
||
```
|
||
http://localhost:15672
|
||
Login: sso / sso_secret
|
||
```
|
||
|
||
## Переменные окружения
|
||
|
||
Скопируйте `.env.example` в `.env`:
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
```
|
||
|
||
Все переменные строго валидируются (Zod). Fast Fail.
|
||
|
||
## Быстрая установка одной командой
|
||
|
||
```bash
|
||
curl -fsSL https://git.lendry.ru/lendry/sso-mvk/raw/main/install.sh | bash
|
||
```
|
||
|
||
Скрипт автоматически:
|
||
1. Проверяет Node.js, Docker, Docker Compose
|
||
2. Скачивает проект в `~/sso-service`
|
||
3. Создаёт `.env` со случайными JWT-секретами
|
||
4. Запускает PostgreSQL, Redis, RabbitMQ через Docker
|
||
5. Устанавливает зависимости, применяет миграции, сидирует БД
|
||
6. Собирает и запускает сервис
|
||
|
||
После установки:
|
||
- **Веб-панель:** http://localhost:3000
|
||
- **Админ:** `admin@sso.local` / `admin123!`
|
||
- **Метрики:** http://localhost:3000/metrics
|
||
- **RabbitMQ UI:** http://localhost:15672 (`sso` / `sso_secret`)
|
||
|
||
### Переменные окружения (опционально)
|
||
```bash
|
||
INSTALL_DIR=/opt/sso curl -fsSL https://git.lendry.ru/lendry/sso-service/raw/branch/main/install.sh | bash
|
||
```
|
||
|
||
## Ручная установка
|
||
|
||
```bash
|
||
# 1. Клонировать
|
||
git clone https://git.lendry.ru/lendry/sso-service.git
|
||
cd sso-service
|
||
|
||
# 2. Настроить окружение
|
||
cp .env.example .env
|
||
# Отредактировать .env под себя
|
||
|
||
# 3. Запустить инфраструктуру
|
||
docker compose up -d
|
||
|
||
# 4. Установить зависимости и применить миграции
|
||
npm ci
|
||
npx prisma generate
|
||
npx prisma db push
|
||
npx ts-node prisma/seed.ts
|
||
|
||
# 5. Собрать и запустить
|
||
npm run build
|
||
node dist/main
|
||
```
|
||
|
||
## Production-деплой
|
||
|
||
```bash
|
||
npm run build
|
||
node dist/main
|
||
```
|
||
|
||
Корректно обрабатывает X-Forwarded-For (TRUST_PROXY).
|
||
|
||
## Публикация на Gitea
|
||
|
||
```bash
|
||
# 1. Создать репозиторий на https://git.lendry.ru → New repository
|
||
# Название: sso-service (или любое другое)
|
||
# Visibility: Public
|
||
|
||
# 2. Инициализировать git и запушить
|
||
cd sso-service
|
||
git init
|
||
git add -A
|
||
git commit -m "Initial commit: SSO service (NestJS, Prisma 7, PostgreSQL)"
|
||
git branch -M main
|
||
git remote add origin https://git.lendry.ru/lendry/sso-service.git
|
||
git push -u origin main
|
||
|
||
# 3. Установка с любого сервера:
|
||
curl -fsSL https://git.lendry.ru/lendry/sso-service/raw/branch/main/install.sh | bash
|
||
```
|
||
|
||
**Важно:** Перед пушем проверьте `install.sh` — `REPO="lendry/sso-service"` и `GIT_HOST="git.lendry.ru"` должны соответствовать вашему Gitea.
|