# V2 — история 2026-06-12 ## Цель Перепроектирование ipwhitelist-app. Начали с модуля аутентификации: Keycloak OIDC → IAM API → готовый sessionUser. ## Архитектура ### Принцип Один вызов `login()` при логине. После этого ни Keycloak, ни IAM не нужны. Переключение компаний — только в сессии (не через IAM switchProfile). ### Ответ IAM (`/api/v1/auth/user`) См. `Files/architect.md` — задокументированы все поля. ### Два стенда | Стенд | URL | Keycloak | IAM | |-------|-----|----------|-----| | Production | `whitelist.nodejsk8s.services.ngcloud.ru` | prod-KC | ✅ | | VM (тест) | `italo.kube5s.ru` | локальный KC на :8080 | ❌ | ### clientId vs companyId - `clientId` = WZ01112 (W-номер) — идентификатор компании в БД - `companyId` = внутренний ID IAM, не W-формат, почти не используется - `allClientIds` = массив всех W-номеров (собираем из `profiles[].client_id`) ## Созданные файлы ``` v2/ ├── server.js # createV2Router() — монтируется в server.js как /v2 ├── src/ │ ├── config/index.js # приоритет: V2_KC_* → KC_* → умолчания │ └── auth/index.js # login(), fetchIamUser(), exchangeCode(), buildAuthUrl(), generateState() └── history/ └── 2026-06-12.md # этот файл ``` ## v2/src/auth/index.js — функции | Функция | Что | Вызывается | |---------|-----|-----------| | `buildAuthUrl(config)` | URL редиректа на Keycloak | `GET /v2/login` | | `exchangeCode(code, config)` | code → access_token | внутри `login()` | | `fetchIamUser(token, iamUrl)` | IAM → профиль | внутри `login()` | | `generateState()` | CSRF-токен | `GET /v2/login` | | `login(code, oidcConfig, iamUrl)` | оркестратор: всё сразу | `GET /v2/callback` | ## v2/src/config/index.js — приоритет ``` V2_KC_BASE_URL → KC_BASE_URL → https://italo.kube5s.ru/realms/ipwhitelist V2_KC_CLIENT_ID → KC_CLIENT_ID → ipwhitelist V2_KC_CLIENT_SECRET → KC_CLIENT_SECRET → '' V2_APP_URL → APP_URL → https://italo.kube5s.ru V2_IAM_API_URL → IAM_API_URL → https://auth-api-dev.ngcloud.ru ``` ## v2/server.js — роуты | Путь | Что | |------|-----| | `GET /v2/` | главная: IAM-данные или редирект на /v2/login | | `GET /v2/login` | → Keycloak | | `GET /v2/callback` | Keycloak → code → login() → сессия → /v2/ | | `GET /v2/logout` | сброс v2_ ключей сессии | Сессионные ключи с префиксом `v2_`: `v2_user`, `v2_token`, `v2_idToken`, `v2_oidcState`. Не пересекаются с основным приложением. ## server.js — изменения Добавлено перед UI-роутером: ```js const { createV2Router } = require('./v2/server'); app.use('/v2', createV2Router()); ``` Порядок: `/healthz` → OIDC → `/api/v1/*` → `/v2/*` → UI (`/*`) ## Что сделано на VM (italo.kube5s.ru) ### Keycloak - Realm `ipwhitelist`, frontendUrl=`https://italo.kube5s.ru` - Client `ipwhitelist`, redirectUris=`['https://italo.kube5s.ru/v2/callback']` - Пользователь: `test` / `test` - Client secret: `40bpIZvumq6jttIB5QtTLcl9AJvAHxlw` - Доступ через nginx: `/realms/*` → Keycloak:8080 ### .env на ВМ Добавлено: `V2_KC_CLIENT_SECRET=40bpIZvumq6jttIB5QtTLcl9AJvAHxlw` ### Деплой ```bash rsync -az -e "ssh ..." /home/naeel/ipwhitelist-app/v2 naeel@5.172.178.213:~/ipwhitelist/ ssh ... 'pm2 restart ipwhitelist' ``` ## Git - Версия: `0.5.57` → `0.5.58` - Коммит: `5c09844` — v2: модуль аутентификации + роутер /v2 - Запушено в `master` на gitea.services.ngcloud.ru ## Ошибки в процессе 1. `rsync v2/` с trailing slash → содержимое v2/ скопировалось в `~/ipwhitelist/`, v2/server.js перезаписал основной server.js - Fix: rsync без trailing slash (`rsync ... v2`) 2. `sed` заменил оба вхождения `italo.kube5s.ru` в конфиге (kcBaseUrl и appUrl) - Fix: переписал файл полностью 3. `kcBaseUrl` без `/realms/ipwhitelist` → редирект на неверный URL Keycloak - Fix: `https://italo.kube5s.ru/realms/ipwhitelist` 4. На ВМ старый `ui/index.js` с багом (дубликат catch) → краш приложения - Fix: rsync --force ui/index.js ## Что дальше 1. Дождаться редеплоя на production (Nubes UI) 2. Проверить `https://whitelist.nodejsk8s.services.ngcloud.ru/v2/login` 3. Если prod-KC не разрешает `/v2/callback` → добавить в VM-шный KC и задать V2_KC_BASE_URL на production 4. Реализовать IAM-фолбэк (если IAM недоступен → JWT claims)