# Интеграция auth-portal ↔ CDN Manager App id: **`cdn`**. Зеркало на стороне портала: [`auth-portal/docs/integrate-cdnmanager.md`](../../auth-portal/docs/integrate-cdnmanager.md) (соседний репозиторий). ## Flow ``` Browser → CDNManager UI (нет token) → redirect AUTH_PORTAL_URL/?return_to=…/auth/callback → login → redirect return_to#access_token=… → /auth/callback сохраняет token (localStorage: cdnmanager_token) → API Authorization: Bearer ``` ## Permissions | Permission | UI | |------------|-----| | `cdn:dashboard:read` | `/` | | `cdn:nodes:read` / `write` | `/nodes` | | `cdn:aliases:read` / `write` | `/aliases` (+ Retarget) | | `cdn:zones:read` / `write` | `/zones` | | `cdn:sync:write` | Sync / Apply | | `cdn:topology:read` | `/topology` | | `cdn:settings:admin` | `/settings/*` | ## Env ```env AUTH_REQUIRED=true AUTH_JWT_SECRET=<тот же JWT_SECRET портала> AUTH_ISSUER=https://auth.shnt.top AUTH_PORTAL_URL=https://auth.shnt.top AUTH_AUDIT_INGEST_SECRET= CLOUDFLARE_API_TOKEN= ``` ```env # apps/web/.env.local (dev SPA) VITE_AUTH_ENABLED=true VITE_AUTH_PORTAL_URL=https://auth.shnt.top ``` В Docker SPA обслуживается API (`STATIC_DIR`): достаточно server-side `AUTH_*` — UI читает `GET /api/v1/auth/config`. В portal Admin → Apps выдайте app `cdn` и нужные `cdn:*`. URL в App Switcher: origin CDNManager (`https://cdn.shnt.top`). ## Checklist 1. Общий `JWT_SECRET` / `AUTH_JWT_SECRET` и одинаковый `AUTH_ISSUER` 2. Origin CDNManager в `RETURN_TO_ALLOWLIST` портала 3. Пользователю выдан app `cdn` 4. `AUTH_REQUIRED=true` в контейнере CDNManager 5. Logout → `{AUTH_PORTAL_URL}/logout` Запуск на сервере: [`deploy-traefik.md`](./deploy-traefik.md) (рекомендуется) или [`deploy-docker.md`](./deploy-docker.md).