From 3c11c206801e0adcbe4dd8b6324eea1f4acd9128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 15 Jun 2026 11:01:13 +0400 Subject: [PATCH] =?UTF-8?q?v2:=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?IAM=20API=20=E2=80=94=20clientID,=20profiles,=20impersonation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- v2/history/2026-06-12.md | 90 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/v2/history/2026-06-12.md b/v2/history/2026-06-12.md index f05a537..546083e 100644 --- a/v2/history/2026-06-12.md +++ b/v2/history/2026-06-12.md @@ -912,3 +912,93 @@ user/index.js → шаблон: | `ADMIN_EMAIL` | `tazet@narod.ru` | Псевдо-админ | Все три (`ORIGINAL`, `TARGET`, `COMPANY`) должны быть заданы — иначе авто-имперсонация не включается. + + +--- + +## IAM API — документация (2026-06-15) + +### Источник: https://auth-api-dev.ngcloud.ru/api/v1/documentation/ + +### GET /api/v1/auth/user — ответ (AuthUserResult) + +```json +{ + "userId": "uuid", + "owner": false, + "isPortal": false, + "sessionId": "uuid", + "privileges": ["system"], + "needChangePassword": false, + "impersonation": { + "is_impersonated": false, // ВСЕГДА есть + "type": "user" | "company", // если активна + "originalUserEmail": "admin@...", // кто имперсонирует + "impersonatedCompanyId": "uuid", // если type=company + "impersonatedUserId": "uuid", // если type=user + "sessionId": 42, + "session_expires_at": "RFC3339" + }, + "permissions": { + "read_only_mode_enabled": false, + "can_write": true, + "is_impersonating": false, + "has_write_permissions": true + }, + "userInfo": { + "email": "user@example.com", // required + "login": "login", + "clientID": "WZ01325", // required (может быть "") + "company": "ООО Пример", + "companyId": "uuid", + "companyNumericId": 1, + "isAdmin": false, // required + "fio": { "fullName": "...", "name": "...", "surname": "...", "secondName": "..." }, + "profiles": [ // массив, может быть пустым + { + "id": 123, // required + "company_id": "uuid", // required + "company_name": "ООО Пример", // required + "client_id": "WZ01325", // НЕ required — может отсутствовать! + "is_active_profile": true // required + } + ] + } +} +``` + +### Ключевые факты + +| Поле | Обязательное? | Может быть пустым? | +|------|-------------|-------------------| +| `userInfo.email` | ✅ required | — | +| `userInfo.clientID` | ✅ required | ⚠️ может быть `""` | +| `userInfo.isAdmin` | ✅ required | — | +| `userInfo.profiles` | массив | может быть `[]` | +| `profiles[].client_id` | ❌ не required | может отсутствовать | +| `profiles[].company_name` | ✅ required | — | +| `impersonation.is_impersonated` | ✅ required | — | + +### Выводы для нашего кода + +1. **`clientID` required, но может быть `""`** — для сотрудников Nubes без компании-клиента. + Именно это происходит с `ntazetdinov@nubes.ru`. +2. **`profiles` может быть пустым `[]`** — нет компаний → нет client_id. +3. **IAM имеет нативную имперсонацию** — `POST /api/v1/impersonation/start`. + Но доступно только админам IAM. `ntazetdinov@nubes.ru` — не админ IAM. +4. **Наш `enhanceImpersonation`** — нужен как обходной путь: ENV-переменные вместо IAM-админки. + +### Что должно происходить + +``` +ntazetdinov@nubes.ru логинится через KC + → IAM: { email: "ntazetdinov@nubes.ru", clientID: "", profiles: [], isAdmin: false } + → fetchIamUser: clientId = "" + → сессия без clientId + → enhanceImpersonation: ORIGINAL совпал → авто-имперсонация + email = "tazet@narod.ru" + clientId = "WZ01325" + allClientIds = ["WZ01325", "WZ01112"] + → resolveContext: req.clientId = "WZ01325" ✅ +``` +