Files
mdm-ordinis/docs/integration/api/auth.md
T
Zimin A.N. bcfb07f547 docs: split integrator guide (Diplodoc) vs internal docs + add build-docs CI
Чёткое разделение audiences:
- docs/ — consumer-facing only, Diplodoc-built. Public contract для
  интеграторов (Альтум, BI, third-party).
- docs-internal/ — operator runbooks, status snapshots, legacy tech pages.
  НЕ в Diplodoc build, НЕ публикуются.

Изменения:
- Move docs/{ops,status,tech} → docs-internal/{ops,status,tech}
- docs/toc.yaml: убраны секции Operations, Архитектура (legacy), Status
- docs/index.md: убран tab "оператор / on-call", focus на integrators
- docs/README.md: rewritten — scope только integrator guide, editorial
  guidelines (no leak internal architecture, stable API contract)
- .yfm: убран явный ignore status/* (теперь не нужно — папка переехала)
- docs-internal/README.md: index для внутренней документации с rationale
  разделения

Scrubbing implementation details из Diplodoc страниц:
- events.md: убраны Strimzi/cluster.142 references, OutboxPoller детали,
  internal alert names (OrdinisOutboxLagHigh, OrdinisOutboxDLQNonEmpty),
  metric names (nsi_outbox_*). Заменены на consumer-observable contract.
- webhooks.md: убраны metric names (nsi_webhook_ssrf_rejected_total),
  alert table (OrdinisWebhookHighFailureRate и т.д.). Retry policy
  переписана на user-side perspective.
- errors.md: убран alert name OrdinisReadApiErrorBudgetBurnFast, Tempo
  endpoint URL, internal connection details.
- x-references.md: OrphanReferenceScanner → general "Ordinis периодически
  детектирует". Убраны metric/alert names. Cascade roadmap без link на
  internal design doc.
- auth.md: убран file path ScopeContext.java.
- bundle-cuod.md: убран Maven module path.
- caching.md: cascade design link заменён на text reference.

CI:
- .gitlab-ci.yml: новый job build-docs (stage: build) — Node 20 alpine,
  pnpm install --frozen-lockfile + pnpm build, artifact docs/_dist на
  неделю. Triggers: auto на docs/**, либо manual web. Готов к follow-up
  pages-deploy job когда host решён.
- Новый pattern .docs-changes для rules.

Build verified clean: 13 HTML pages, 6.9M, no broken links/refs.
2026-05-07 23:27:03 +03:00

113 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Авторизация
Ordinis принимает JWT от Keycloak realm `nstart`:
- **Issuer:** `https://auth.nstart.space/realms/nstart`
- **Алгоритм:** RS256
- **JWK Set discoverится** через `/.well-known/openid-configuration`
## Service account (m2m)
Для backend-to-backend интеграции (типичный сценарий):
1. Запросить у Ordinis team создание клиента в realm `nstart`.
2. Назначить role: `ordinis-public` / `ordinis-internal` / `ordinis-restricted`
(по нужному scope, см. ниже).
3. Получить `client_id` + `client_secret`. Хранить в Vault либо secret manager,
**никогда** в коде.
## Получение access token
```bash
curl -X POST https://auth.nstart.space/realms/nstart/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=<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://auth.nstart.space/realms/nstart` | `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 `auth.nstart.space` health |
## Дальше
→ [Read-side endpoints](read-endpoints.md) — что можно читать с этим токеном.