В этом руководстве один upstream API ставится за edge, и браузерное приложение вызывает его с cookie сессии. В конце пользователь читает свои заказы, не может читать чужие, а у вас есть команды curl, которые это доказывают. Нужна работающая установка с тенантом, привязанным к edge, и ваш API, доступный для edge по сети.
В примере используются эти имена. Замените их своими.
| Что | Значение |
|---|---|
Публичный адрес edge (edge-url) | https://edge.example.com |
Публичный адрес auth | https://id.example.com |
| Ваше браузерное приложение | https://app.example.com |
| Upstream API | http://orders.internal.example.com:8080 |
| ID ресурса | orders-api |
| Клиент | acme-web |
| Разрешение, роль | orders:read, customer |
| Пресет | web |
Предварительные условия
- Установка с
central,authиedge(Запуск Versola локально). - Тенант с нужным профилем, привязанный к вашему edge в разделе Tenants. См. Профили безопасности.
- В
centralнастроен бэкенд УЦ для клиентских сертификатов, потому что веб-клиент заedgeполучает выпущенный сертификат (Клиентские сертификаты edge). Цели CLI настраивают его сами. - Upstream API с двумя маршрутами:
GET /ordersиGET /users/{userId}/orders.
1. Зарегистрируйте ресурс
-
Откройте Resources и нажмите + Create Resource.
-
Задайте Resource ID
orders-apiи Absolute resource URIhttp://orders.internal.example.com:8080. В URI нет пути, query и fragment. -
Выберите тип Internal. Тогда
edgeвызывает ваш API с HTTP Basic и никогда не пересылает токен пользователя. -
В Audience отметьте клиента
acme-web, когда он появится (шаг 3). К этой карточке можно вернуться позже. -
Нажмите Create resource и скопируйте секрет, который покажет баннер. Он показывается один раз. Настройте ваш API на Basic-аутентификацию: пользователь
orders-api, пароль — этот секрет. Подробности в Как зарегистрировать ресурс. -
На карточке Endpoints нажмите Edit endpoints, затем Add и добавьте
GET /orders. Правила оставьте пустыми. -
Снова нажмите Add и добавьте
GET /users/{userId}/orders. В Allow (CEL) введите:request.path.params.userId == token.sub -
Нажмите Save endpoints.
Правило сравнивает userId из URL с claim sub токена вызывающего. Остальные поля и переменные описаны в разделе Политики эндпоинтов.

2. Выдайте доступ через разрешение и роль
Пока эндпоинт не покрыт разрешением, он отвечает 403.
- Откройте Permissions, создайте
orders:readи привяжите оба эндпоинтаorders-api(Как зарегистрировать разрешение). - Откройте Roles, создайте
customerи добавьте в нееorders:read(Как зарегистрировать роль). - Откройте Users и назначьте тестовому пользователю роль
customer.
3. Создайте клиента и пресет авторизации
-
Откройте Clients и запустите мастер создания. На первом шаге выберите Web app и задайте ID клиента
acme-web. -
Добавьте redirect URI
https://edge.example.com/complete. Это маршрут/completeвedge, который принимает код отauth. -
Завершите мастер и вернитесь в поле Audience ресурса, чтобы добавить
acme-web, если вы пропустили это раньше (Как зарегистрировать клиента). -
В клиенте откройте Authorization Presets и нажмите + Add Preset:
Поле Значение Preset ID webRedirect URI https://edge.example.com/completeScopes openidResponse Type codePost-login redirect URI https://app.example.com/Post-logout redirect URI (optional) https://app.example.com/logged-outSession cookie domain, path (optional) оставьте пустыми: cookie на хосте edge, путь/ -
Нажмите Save Presets.
edgeзагружает пресеты вместе с остальной конфигурацией, так что подождите доconfiguration-cache-refresh-interval(по умолчанию генерируется 5 минут, локально 1 минута).
4. Направьте браузерное приложение на edge
- Вход. Отправьте браузер на
https://edge.example.com/login/web. После входа он вернется наhttps://app.example.com/и будет держать cookieEDGE_SESSION, которую JavaScript прочитать не может. Чтобы потребовать свежий или более сильный вход, добавьте в URLacr_valuesилиmax_age. - Вызов API. Запрашивайте
https://edge.example.com/resources/orders-api/ordersсcredentials: 'include'. Часть после/resources/orders-apiсопоставляется с зарегистрированными эндпоинтами. - Один сайт, один origin. Cookie имеет
SameSite=Strict, поэтому приложение иedgeдолжны быть на одном сайте.edgeне отправляет заголовки CORS, поэтому отдавайте приложение иedgeс одного origin, например маршрутизируйте/resources/*и/login/*с прокси вашего сайта наedge. - Истекшая сессия. Если cookie нельзя обновить,
edgeотвечает401с заголовкомLocation: /login/web. Перейдите по нему. - Выход. Отправьте браузер на
https://edge.example.com/logout/web.
5. Проверьте через curl
Войдите в браузере и скопируйте значение cookie EDGE_SESSION из инструментов разработчика. Оно имеет вид web:<access token>. ID пользователя, то есть claim sub, возьмите из токена или из раздела Users. Токен, привязанный к сертификату edge, работает только из cookie, поэтому отправляйте его как cookie, а не как Authorization: Bearer.
Прочитайте свои заказы:
curl -i -H "Cookie: EDGE_SESSION=web:<access token>" \
https://edge.example.com/resources/orders-api/users/<your-user-id>/orders
HTTP/1.1 200 OK
...
Тело — то, что вернет ваш API. Теперь запросите чужие заказы:
curl -i -H "Cookie: EDGE_SESSION=web:<access token>" \
https://edge.example.com/resources/orders-api/users/<another-user-id>/orders
HTTP/1.1 403 Forbidden
Правило вернуло false. edge пишет в лог access_rule_denied для этого запроса и не отправляет тело. Upstream вызова не видел. Без учетных данных:
curl -i https://edge.example.com/resources/orders-api/orders
HTTP/1.1 401 Unauthorized
Путь, под который не подходит ни один эндпоинт, при действующей сессии дает 404.
DPoP или токены, привязанные к сертификату
Шаги выше обслуживают браузер. Если вызывающий — другая система (банк, бэкенд партнера, мобильное приложение), он присылает собственный токен в заголовке Authorization, и вы выбираете, как этот токен привязан к вызывающему. edge решает по claim cnf (Токены с привязкой к отправителю).
DPoP (cnf.jkt) | Привязка к сертификату (cnf.x5t#S256) | |
|---|---|---|
| Что доказывает вызывающий | Владение ключом, подписанным proof в каждом запросе | Владение клиентским сертификатом, в TLS-handshake |
| Порт | Обычный порт edge | Mutual-TLS listener edge, MPORT |
| Заголовок | Authorization: DPoP и DPoP | Authorization: Bearer |
| Где живет ключ | В приложении или в хранилище ключей устройства | В сертификате, выпущенном УЦ, с продлением |
| Что нужно вызывающему | Реализация DPoP, повтор запроса с nonce, если он требуется | HTTP-клиент с mTLS и план продления сертификата |
| Что запускаете вы | Ничего лишнего. Блок dpop в edge | Блок mutual-tls с серверным сертификатом, УЦ вызывающего в trusted-certificates, а если у эндпоинтов включен fetchUserInfo, то блок native в edge и edge-trusted-certificates в auth |
| Токен после продления у вызывающего | Не затронут, пока ключ тот же | Токен назван на старый сертификат. Вызывающий получает новый токен с новым сертификатом |
| Типичный вызывающий | Мобильные и десктопные приложения, сервисы и скрипты | Банки и партнеры по FAPI 2.0, бэкенды, у которых уже есть клиентский сертификат |
Выбирайте DPoP, если вызывающий не умеет mutual TLS или вам не нужен второй публичный порт. Выбирайте токены, привязанные к сертификату, если вызывающий — регулируемый бэкенд, который уже аутентифицируется сертификатом (tls_client_auth), если этого требуют правила вашей отрасли или если вы хотите, чтобы доказательство было в транспорте, а не в каждом запросе. Токен, привязанный и к ключу, и к сертификату, edge отклоняет при любом предъявлении, поэтому выбирайте для клиента одну привязку.
Чтобы обслуживать вызывающего с сертификатом:
- Зарегистрируйте клиента с
authMethod: tls_client_auth(Как зарегистрировать клиента). Его токены будут привязаны к сертификату. - Убедитесь, что у тенанта настроен путь клиентского сертификата (Клиентские сертификаты и их продление).
- Добавьте в конфигурацию
edgeблокmutual-tlsс УЦ клиентского сертификата вtrusted-certificates(Конфигурация edge). - Если у эндпоинта включено Fetch userinfo, дайте
edgeблокnative, а вauthзадайтеmutual-tls.edge-trusted-certificatesс УЦ edge. - Вызывающий запрашивает токен в
authсо своим сертификатом и вызываетhttps://<адрес mutual-TLS>/resources/orders-api/ordersсAuthorization: Bearer <access token>и тем же сертификатом.
curl -i --cert bank.crt --key bank.key \
-H "Authorization: Bearer <access token>" \
https://api.example.com:8083/resources/orders-api/orders
Тот же токен на обычном порту получает 401, а в журнале certificate_bound_token_outside_session.
Если не работает
| Что вы видите | Что проверить |
|---|---|
404 на /login/web | Пресет не сохранен или edge еще не перечитал конфигурацию. Подождите один интервал обновления |
403 на каждый вызов | У роли нет разрешения или разрешение не привязано к эндпоинту. Код permission_denied в логе edge это подтверждает. Изменения ролей и разрешений тоже доходят до одного интервала обновления |
403 с audience_denied в логе | Клиента нет в Audience ресурса |
403 на ваши собственные заказы | token.sub — не тот ID пользователя, что в URL |
500 | Правило не вычисляется. Ищите access_rule_failed в логе |
Ваш API отвечает 401 | Он не принимает Basic-учетные данные orders-api:<secret> |
Что дальше
- Политики эндпоинтов: подстановка заголовков идентичности, step-up для чувствительных эндпоинтов.
- Обзор edge: что
edgeделает с каждым запросом. - Как собрать поток нативного мобильного приложения: тот же API для мобильного приложения.