# Архитектура авторизации облачного портала > Со слов пользователя, на основе JWT из localStorage --- ## Схема аутентификации ``` Пользователь (браузер) │ ▼ Keycloak (keycloak.nubes.ru, realm=cloud) │ Authorization Code Flow │ client_id=deck.ngcloud.ru │ scope=openid email ▼ auth-api.ngcloud.ru (СОБСТВЕННЫЙ сервис) │ Создаёт свой JWT (issuer="auth-api") │ Подпись: RS256 (RSA) ▼ deck.ngcloud.ru (портал) │ Микро-фронтенды (SPA): dashboard, contracts, services, ... │ JWT хранится в localStorage: authApiTokens.access_token ▼ IPWhiteList (наш сервис) ← будет встроен как микро-фронтенд в портал ``` ## Важное - JWT подписывает **не Keycloak**, а **auth-api** - Issuer: `"auth-api"`, алгоритм: `RS256` - Для валидации нужен публичный ключ auth-api (JWKS или статический) --- ## Структура JWT (access_token) _Из localStorage → authApiTokens → access_token_ | Поле | Тип | Значение (пример) | Назначение | |---|---|---|---| | `iss` | string | `"auth-api"` | Кто выпустил токен | | `sub` | string | `"0199e325-..."` | UUID пользователя | | `iat` | number | `1780073927` | Выпущен (Unix time) | | `exp` | number | `1780117127` | Истекает (~12 часов) | | `jti` | string | `"4d8d7240-..."` | Уникальный ID токена | | `ClientID` | string | `"WZ01325"` | ID **ТЕКУЩЕЙ** компании пользователя | | `company_id` | string (UUID) | `"3e64aac6-..."` | UUID компании | | `company_name` | string | `"Тест"` | Название компании | | `email` | string | `"tazet@narod.ru"` | Email (для аудита) | | `login` | string | `"tazet@narod.ru"` | Логин | | `firstname` | string | `"Наиль"` | Имя | | `lastname` | string | `"Тазетдинов"` | Фамилия | | `token_type` | string | `"access"` | Тип токена | ## Что НЕ в JWT (отдельный authData в localStorage) _Из localStorage → authData → v_ | Поле | Значение | Где используется | |---|---|---| | `userInfo.isAdmin` | `false` (boolean) | ⚠️ Признак администратора | | `profiles[]` | Массив `{company_id, company_name, is_active_profile}` | Список всех компаний пользователя | | `roles[]` | Массив `{role_id, role_name}` | Роли пользователя | | `permissions.can_write` | `false` | Есть ли права на запись | --- ## Открытые вопросы (нужно уточнить с командой портала) 1. **Валидация JWT.** У auth-api есть JWKS (`/.well-known/jwks.json`)? Или ключ статический? Как нашему сервису проверять подпись? 2. **isAdmin.** Флаг админа есть только в authData localStorage, но не в JWT. Как наш сервис узнает что пользователь — админ? - Вариант A: попросить добавить `isAdmin` в JWT - Вариант B: наш сервис ходит в auth-api за authData - Вариант C: смотреть на `ClientID == "WZ01112"` (как в ТЗ) 3. **Список компаний.** В JWT — только одна компания. В authData.profiles — массив. Для переключателя компаний в нашем UI — откуда брать список? - Вариант A: попросить добавить `profiles` в JWT - Вариант B: наш сервис ходит в auth-api 4. **Как наш сервис попадает в портал?** Как микро-фронтенд (SPA) или как отдельная страница с редиректом? Куда монтироваться?