# Авторизация Ordinis принимает JWT от Keycloak realm `altum`: - **Issuer:** `https://altum.nstart.cloud/auth/realms/altum` - **Алгоритм:** RS256 - **JWK Set discoverится** через `/.well-known/openid-configuration` ## Service account (m2m) Для backend-to-backend интеграции (типичный сценарий): 1. Запросить у Ordinis team создание клиента в realm `altum`. 2. Назначить role: `ordinis-public` / `ordinis-internal` / `ordinis-restricted` (по нужному scope, см. ниже). 3. Получить `client_id` + `client_secret`. Хранить в Vault либо secret manager, **никогда** в коде. ## Получение access token ```bash curl -X POST https://altum.nstart.cloud/auth/realms/altum/protocol/openid-connect/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=altum-backend" \ -d "client_secret=" ``` Ответ: ```json { "access_token": "eyJhbGciOi...", "expires_in": 300, "token_type": "Bearer" } ``` {% note warning %} Кэшируй токен с TTL = `expires_in - 30` (буфер на retries) в backend memory. Не делай новый token request на каждый API call — Keycloak rate limits и латентность. {% endnote %} ## Использование Каждый запрос требует header: ``` Authorization: Bearer eyJhbGciOi... ``` Без header → `401 Unauthorized`. С невалидным/expired токеном → `401`. Token валиден но scope не позволяет доступ к словарю → `403 Forbidden`. ## Маппинг ролей в DataScope Ordinis использует трёхуровневый доступ к словарям через `scope` field в `DictionaryDefinition`: | Keycloak роль | Доступные scopes | |---|---| | `ordinis-public` | `PUBLIC` | | `ordinis-internal` | `PUBLIC` + `INTERNAL` | | `ordinis-restricted` | `PUBLIC` + `INTERNAL` + `RESTRICTED` | Альтернативный синтаксис ролей (для compat с другими сервисами в realm): суффикс `-PUBLIC|INTERNAL|RESTRICTED` (например `altum-PUBLIC`, `geoportal-INTERNAL`). Маппинг встроен в auth layer Ordinis. {% note info %} Альтум consumer на проде использует role `ordinis-internal` — доступ к PUBLIC + INTERNAL справочникам. RESTRICTED закрытый только для специально authorized clients. {% endnote %} ## Refresh tokens `client_credentials` flow **не поддерживает refresh tokens** — это m2m flow без user session. Получай новый access token при истечении. Если используешь user-on-behalf flow (rare для backend) — refresh token работает, см. Keycloak документацию. ## Multiple environments | Среда | Issuer | Realm | |---|---|---| | prod | `https://altum.nstart.cloud/auth/realms/altum` | `nstart` | | staging | same | same | | local | same либо local Keycloak (опц) | same | Один Keycloak realm для всех сред. Service accounts shared (но `client_id` обычно различается per env: `altum-backend-prod`, `altum-backend-staging`). ## Troubleshooting | Симптом | Причина | Fix | |---|---|---| | 401 на каждый запрос | Token expired | Refresh с TTL buffer | | 401 на новый token | Invalid client_secret | Re-fetch у Ordinis team | | 403 на конкретные dictionaries | Scope mismatch | Запросить upgrade role у Ordinis team | | 500 от Ordinis | Issuer unreachable / JWK fetch fail | Check `altum.nstart.cloud/auth` health | ## Дальше → [Read-side endpoints](read-endpoints.md) — что можно читать с этим токеном.