docs: архитектура авторизации облачного портала (из JWT)
This commit is contained in:
@@ -0,0 +1,83 @@
|
|||||||
|
# Архитектура авторизации облачного портала
|
||||||
|
|
||||||
|
> Со слов пользователя, на основе 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) или как отдельная страница с редиректом? Куда монтироваться?
|
||||||
Reference in New Issue
Block a user