feat: добавляет документацию для сервиса авторизации hr-appeals
build-and-deploy / prepare (push) Successful in 1s
Tests / frontend-test (push) Successful in 11s
build-and-deploy / build-and-push (., Dockerfile, hr-appeals-web) (push) Successful in 11s
build-and-deploy / build-and-push (server, server/Dockerfile, hr-appeals-auth) (push) Successful in 5s
build-and-deploy / deploy (push) Successful in 15s
build-and-deploy / prepare (push) Successful in 1s
Tests / frontend-test (push) Successful in 11s
build-and-deploy / build-and-push (., Dockerfile, hr-appeals-web) (push) Successful in 11s
build-and-deploy / build-and-push (server, server/Dockerfile, hr-appeals-auth) (push) Successful in 5s
build-and-deploy / deploy (push) Successful in 15s
This commit is contained in:
@@ -0,0 +1,63 @@
|
|||||||
|
# hr-appeals-auth
|
||||||
|
|
||||||
|
Сервис получает app-only токен Azure AD (JWT client
|
||||||
|
assertion) и используется для авторизованных запросов к внутреннему API
|
||||||
|
`api.tnsu.kz`. Сам токен наружу не отдаётся — из HTTP-эндпоинтов сервиса
|
||||||
|
доступны только `/healthz` и `/diag/token` (последний подтверждает, что
|
||||||
|
токен получен, но не возвращает его значение). Детали получения токена — в
|
||||||
|
[graphAuth.ts](src/graphAuth.ts).
|
||||||
|
|
||||||
|
## Переменные окружения
|
||||||
|
|
||||||
|
| Переменная | Назначение |
|
||||||
|
|---|---|
|
||||||
|
| `GRAPH_TENANT_ID` | Tenant ID Azure AD |
|
||||||
|
| `GRAPH_CLIENT_ID` | Client ID App Registration, к которому привязан сертификат `SPFxDeploy` |
|
||||||
|
| `GRAPH_CERT_PATH` | Путь к `SPFxDeploy_cert.pem` внутри контейнера (см. `docker-compose.yml` в корне репозитория) |
|
||||||
|
| `GRAPH_KEY_PATH` | Путь к `SPFxDeploy_key.pem` внутри контейнера |
|
||||||
|
| `GRAPH_SCOPE` | OAuth-scope запрашиваемого токена. **По умолчанию `https://graph.microsoft.com/.default` — для api.tnsu.kz это неверное значение.** Нужно явно указать App ID URI, под которым `api.tnsu.kz` зарегистрирован в Azure AD, например `api://<app-id-uri-api.tnsu.kz>/.default`. Точное значение уточнить у того, кто регистрировал API в Azure AD |
|
||||||
|
| `PORT` | Порт HTTP-сервера сервиса, по умолчанию `3000` |
|
||||||
|
|
||||||
|
## Как обратиться к api.tnsu.kz с авторизацией
|
||||||
|
|
||||||
|
Токен запрашивается через `getAppOnlyToken()` и передаётся в заголовке
|
||||||
|
`Authorization: Bearer <token>`. Функция сама кэширует токен до истечения,
|
||||||
|
повторно вызывать её на каждый запрос не накладно — за сеть она сходит
|
||||||
|
только когда кэш устарел.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { getAppOnlyToken } from './graphAuth';
|
||||||
|
|
||||||
|
async function callApiTnsu(path: string, init: RequestInit = {}) {
|
||||||
|
const token = await getAppOnlyToken();
|
||||||
|
|
||||||
|
const response = await fetch(`https://api.tnsu.kz${path}`, {
|
||||||
|
...init,
|
||||||
|
headers: {
|
||||||
|
...init.headers,
|
||||||
|
Authorization: `Bearer ${token}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`api.tnsu.kz ответил ${response.status}: ${await response.text()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Перед тем как писать реальные вызовы, убедитесь, что обмен сертификата на
|
||||||
|
токен вообще работает — на запущенном сервисе:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:3000/diag/token
|
||||||
|
# {"ok":true} — сертификат подошёл, токен получен и закэширован
|
||||||
|
# {"ok":false,"error":"..."} — см. текст ошибки: неверный tenant/client id,
|
||||||
|
# истёкший сертификат, неверный scope и т.п.
|
||||||
|
```
|
||||||
|
|
||||||
|
Если `/diag/token` отвечает `ok:true`, но реальный вызов `api.tnsu.kz`
|
||||||
|
падает с `401`/`403` — вероятная причина в `GRAPH_SCOPE`: токен получен, но
|
||||||
|
выпущен не для этого API (Azure AD не проверяет аудиторию на этапе выдачи
|
||||||
|
токена — она проверяется уже на стороне `api.tnsu.kz`).
|
||||||
Reference in New Issue
Block a user