# Эндпоинты, с которыми взаимодействует auth-flow-frontend Документ описывает внешние эндпоинты, внутренние роуты и каналы межвкладочной коммуникации микрофронтенда аутентификации `auth-flow-frontend`. ## Как устроено взаимодействие Приложение отвечает только за аутентификацию по протоколу **OIDC (Authorization Code Flow + PKCE)**. Прямых REST-запросов к бэкенд-сервисам Sarex у него **нет** — всё сетевое взаимодействие идёт с провайдером идентификации **Zitadel** через обёртку `@sarex-team/sdk-js/zitadel` (поверх `oidc-client`). Клиент создаётся в `src/config/zitadel.ts` (`createZitadelAuth(configZitadel)`). Базовый адрес провайдера (`authority`, issuer) и `client_id` берутся из `localStorage` во время работы, а не задаются сборкой. OIDC-клиент сам находит конкретные эндпоинты issuer'а через discovery-документ `/.well-known/openid-configuration`. ## Провайдер идентификации (Zitadel) по окружениям Фактический `authority` подставляется хостовым приложением через `localStorage` (`STORAGE.AUTHORITY`) — в самом `auth-flow-frontend` хосты не захардкожены. Ниже — известные для платформы Sarex значения (справочно): | Окружение | `authority` (issuer) | | --- | --- | | `stage` | `https://idp.dev.stage.sarex.io` | | `prod` | `https://login.sarex.io` | ## OIDC-эндпоинты провайдера Обнаруживаются через discovery и вызываются `oidc-client` относительно `authority`. Итоговые пути определяются метаданными issuer'а. | Эндпоинт (метаданные) | Метод | Где инициируется | Назначение | | --- | --- | --- | --- | | `/.well-known/openid-configuration` | GET | инициализация `UserManager` | Discovery метаданных провайдера | | `authorization_endpoint` | GET (redirect) | `LoginPage` → `zitadel.authorize()` | Старт авторизации, редирект на форму входа | | `token_endpoint` | POST | `AuthCallbackPage` → `zitadel.userManager.signinCallback()` | Обмен `code` → access/refresh/id токены | | `jwks_uri` | GET | `oidc-client` | Ключи для проверки подписи токенов | | `userinfo_endpoint` | GET | `oidc-client` (при необходимости) | Профиль пользователя | | `end_session_endpoint` | GET (redirect) | `LogoutPage` → `zitadel.signout()` | Завершение сессии (логаут) | Параметры OIDC-запросов (из `configZitadel`): - `response_type`: `code` - `scope`: `openid profile email offline_access urn:zitadel:iam:user:metadata` - `redirect_uri`: `${window.location.origin}/auth/callback` - `post_logout_redirect_uri`: `${window.location.origin}/login` - `revokeTokensOnSignout`: `false`, `automaticSilentRenew`: `false` ## Внутренние роуты приложения Диспетчеризация — в `src/App.tsx` по `window.location.pathname` (роуты из `src/config/urls.ts`). | Роут | Страница | Метод | Назначение | | --- | --- | --- | --- | | `/auth/callback` | `AuthCallbackPage` | — | Обработка OIDC-колбэка: `signinCallback()`, установка токенов, рассылка события в `login_channel`. Дефолт для неизвестных путей | | `/auth/error` | `AuthErrorPage` | — | Отображение ошибки аутентификации (параметры `error`, `error_description`, `state`, `message` из query) | | `/login` | `LoginPage` (dev) | — | Кнопка входа (`zitadel.authorize()`) | | `/logout` | `LogoutPage` (dev) | — | Кнопка выхода (`zitadel.signout()`) | | `/` | `MainPage` (dev) | — | Dev-навигация (login/logout) | | `/ping` | nginx | GET | Healthcheck, отдаёт `{"result": "ok"}` | ## Поток аутентификации (кратко) 1. `LoginPage` вызывает `zitadel.authorize()` → редирект на `authorization_endpoint` Zitadel. 2. Провайдер возвращает пользователя на `redirect_uri` = `/auth/callback` с `code`. 3. `AuthCallbackPage` вызывает `signinCallback()` → обмен `code` на токены через `token_endpoint`. 4. Токены сохраняются (`setTokensInfo` → `storage.setAccessToken/setRefreshToken/setIdentityToken`), снимается флаг логаута. 5. Результат рассылается остальным вкладкам, происходит закрытие overlay-окна (`window.opener`) или переход на `/` (`HOME`). 6. При ошибке — редирект на `/auth/error` с деталями. ## Межвкладочная и оконная коммуникация | Канал | Ключ / имя | Назначение | | --- | --- | --- | | `BroadcastChannel` | `login_channel` | Сообщения `{ type: "login_success" }` и `{ type: "login_error", reason }` между вкладками | | `localStorage` | `sarex_logout` (`LOGOUT_STORAGE_KEY`) | Состояние логаута между вкладками (`logoutAt`, `owner`, `reason`) | | window events | `setTokensInfoIntoWindowEvents` (`@sarex-team/sdk-js`) | Оповещение хостового приложения об обновлении токенов (`reason: "auth_callback"`) | | `window.opener` | — | Режим overlay: после успешного входа окно закрывается (`window.close()`) | ## Обработка ошибок Логика — в `src/utils/authError.ts`; отображение — `AuthErrorPage`. - Параметры ошибки читаются из query-строки колбэка: `error`, `error_description`, `state`, `message` (`parseAuthErrorFromSearch`). - Причина ошибки: `error_description` → `message` → `error` → `"Unknown error"` (`getAuthErrorReason`). - URL страницы ошибки собирается `buildAuthErrorUrl` (query из непустых параметров, иначе просто `/auth/error`). - Если контекста ошибки нет — редирект на `/` (`HOME`). - Пользователю доступны кнопки «Скопировать детали ошибки» (`formatAuthErrorForCopy`) и «Вернуться на форму входа» (`/login`), а также ссылка в поддержку `mailto:support@sarex.io`.