Files
auth-portal/docs/integrate-mikrotikmanager.md
DenozordecandCursor fd7d9fd13c
quality / commitlint (push) Skipped
quality / changes (push) Successful in 7s
quality / docker-check (push) Skipped
quality / web (push) Successful in 40s
quality / api (push) Successful in 36s
CD / quality (push) Successful in 1m37s
CD / publish (push) Successful in 1m40s
feat(apps): добавить MikrotikManager app id mm
Регистрация mm в каталоге приложений, permissions mm:*, target-app и docs.

Co-authored-by: Cursor <[email protected]>
2026-09-04 20:38:27 +07:00

113 lines
3.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Интеграция auth-portal ↔ MikrotikManager
Единый вход: пользователь логинится на auth-portal, получает JWT, переходит в MikrotikManager с токеном в URL fragment. Backend MM проверяет JWT и права `mm:*`.
## Архитектура
```
Browser → MikrotikManager UI (нет token)
→ redirect AUTH_PORTAL_URL/?return_to=…/auth/callback
→ login
→ redirect return_to#access_token=…
→ MM /auth/callback сохраняет token (mmapp_token)
→ API Authorization: Bearer …
```
Общий секрет: `JWT_SECRET` / `AUTH_JWT_SECRET` (HS256). Issuer: `ISSUER` / `AUTH_ISSUER`.
App id в портале: **`mm`** (каталог permissions).
## Локальный запуск
### 1. auth-portal
```bash
cd auth-portal
pnpm install
# JWT_SECRET=dev-secret-change-me
# RETURN_TO_ALLOWLIST=.shnt.top,localhost,http://localhost:3000
pnpm --filter @authportal/api dev # :8080
pnpm --filter web dev # :5175
```
Bootstrap: `[email protected]` / `admin`. В админке выдайте app **mm** и permissions `mm:*`.
### 2. MikrotikManager
```bash
cd MikrotikManager
npm install
```
Backend `backend/.env`:
```env
AUTH_REQUIRED=true
AUTH_JWT_SECRET=dev-secret-change-me
AUTH_ISSUER=https://auth.shnt.top
AUTH_PORTAL_URL=http://localhost:5175
CORS_ORIGIN=http://localhost:3000
```
Frontend: `NEXT_PUBLIC_AUTH_PORTAL_URL=http://localhost:5175` (или runtime `GET /api/auth/config` через proxy).
```bash
npm --prefix backend run dev
npm run dev
```
Откройте `http://localhost:3000` → редирект на portal → после логина NavUser показывает имя/email.
## Permissions ↔ API / UI
Иерархия: `admin``write``read` в рамках одной секции.
| Permission | API (prefix) | UI |
|------------|--------------|-----|
| `mm:dashboard:read` | sidebar-counts, events (GET) | `/dashboard` |
| `mm:servers:read` / `write` | `/api/servers*` | `/servers` |
| `mm:filters:read` / `write` | `/api/filters*` | `/filters`, GRE |
| `mm:bgp:read` / `write` | `/api/bgp*` | BGP |
| `mm:uptime:read` / `write` | `/api/uptime*` | `/uptime` |
| `mm:traffic:read` / `write` | `/api/traffic*` | `/traffic` |
| `mm:alerts:read` / `write` | `/api/alerts*` | `/alerts` |
| `mm:backups:read` / `write` | `/api/backups*` | `/backups` |
| `mm:certificates:read` / `write` | `/api/certificates*` | certificates |
| `mm:network:read` / `write` | `/api/network*`, OSPF, recursive, probes | network |
| `mm:settings:admin` | `/api/system/*`, scheduler, evobgp settings | `/settings` |
Без app `mm` в JWT `apps`**403** на защищённые `/api/*`.
`AUTH_REQUIRED=false` — API открыт (dev без portal).
## App Switcher
`CURRENT_APP_ID = mm`. Публичный конфиг: `GET {AUTH_PORTAL_URL}/api/v1/app-switcher`.
## Logout (SSO)
Очистить `mmapp_token` → редирект на **`{AUTH_PORTAL_URL}/logout`**.
## Production
См. общий стек CDN+MM: `deploy/docker-compose.cdn-mm.yml` / `deploy/env.cdn-mm.example`.
```env
AUTH_REQUIRED=true
AUTH_JWT_SECRET=<тот же JWT_SECRET портала>
AUTH_ISSUER=https://auth.shnt.top
AUTH_PORTAL_URL=https://auth.shnt.top
CORS_ORIGIN=https://mm.shnt.top
```
В portal: `RETURN_TO_ALLOWLIST` включает `https://mm.shnt.top` (или `.shnt.top`).
## Troubleshooting
| Симптом | Причина |
|---------|---------|
| SSO loop | разный `JWT_SECRET` или `ISSUER` |
| 403 «Нет доступа к приложению» | нет app `mm` у пользователя |
| 403 «Недостаточно прав» | нет нужного `mm:…` |
| return_to rejected | origin MM не в `RETURN_TO_ALLOWLIST` |