Versola состоит из трех сервисов, сгруппированных в три уровня, и прокси, который маршрутизирует трафик и отдает консоль администратора. Здесь описано, чем владеет каждый уровень и как запрос проходит через них. Развертывание на этой странице не рассматривается: см. раздел Эксплуатация.
Три уровня
| Уровень | Сервис | Чем владеет |
|---|---|---|
| Управления (control) | central | Источник истины для конфигурации: тенанты, клиенты, scope, роли, разрешения, ресурсы, ключи подписи. Предоставляет Central API |
| Данных (data) | auth | Сервер OAuth 2.0 / OpenID Connect: вход, токены, сессии, пользователи и их учетные данные |
| Трафика (traffic) | edge | Обратный прокси с аутентификацией и авторизацией перед вашими API. Служит шлюзом и для браузерных приложений (вход, сессии), и для нативных мобильных |
auth и edge получают конфигурацию из central. Администраторы меняют конфигурацию только через central: в консоли администратора или через Central API.
Уровень управления: central
central хранит конфигурацию и обслуживает Central API (OpenAPI: central.yaml). На пустой базе он один раз применяет начальную конфигурацию (bootstrap). Дальше конфигурацию меняют через консоль.
Консоль администратора — статическое одностраничное приложение. Она собрана в образ versola-tools и отдается прокси по адресу /central/admin/. У консоли нет собственного сервера: ее вызовы API уходят на /central/* прокси, который направляет их через edge в central, то есть между консолью и central стоит edge.
Уровень данных: auth
auth реализует потоки OAuth 2.0 и OIDC: /authorize, /par, /token, /introspect, /revoke, /userinfo, выход и discovery. Он ведет диалог входа (пароль, OTP, passkey), выпускает и подписывает токены и хранит пользователей. Дополнительно он может поднять второй TLS-listener для mutual TLS (см. токены с привязкой к отправителю).
Уровень трафика: edge
У edge три задачи:
- Сессии браузера. Он работает как OAuth-клиент для веб-приложений (
/login/{presetId},/complete). Токены остаются на стороне сервера, а браузер получает cookieEDGE_SESSION(HttpOnly,Secure,SameSite=Strict). Refresh-токены хранятся в схемеedge, а истекшие access-токеныedgeобновляет сам. - Прокси с политиками. Он проксирует
/resources/{resourceId}/{path}к вашему upstream API. Для каждого запроса проверяются отзыв токена, его привязка, разрешения, audience и CEL-правила эндпоинта, после чегоedgeдобавляет заголовки или параметры запроса, построенные из токена и данных пользователя. См. Edge. - Шлюз для нативных приложений. Мобильные приложения вызывают эндпоинты
/native/*, аedgeпроводит авторизацию от их имени с помощью PAR и ключа DPoP, который хранится на устройстве. См. Нативные приложения.
Базы данных
Каждый сервис владеет своими данными и своей историей миграций, а друг с другом сервисы общаются только по HTTP API. В стандартной топологии у каждого сервиса своя база Postgres, поэтому они масштабируются, резервируются и отказывают независимо. В минимальном варианте все три сервиса работают в одной базе, каждый в своей схеме (auth, central, edge). Именно так устроены versola bootstrap local и деплой на VPS. Ни в одной из топологий сервис не читает таблицы другого сервиса.
flowchart TB
admin[["👤 Administrator"]]
user[["👤 End user"]]
subgraph versola["⚡ Versola"]
proxy["versola-proxy<br/><i>nginx</i><br/>Routing and admin console files"]
edge["edge<br/><i>traffic plane</i><br/>Sessions, policies, native gateway"]
auth["auth<br/><i>data plane</i><br/>OAuth 2.1 and OIDC server"]
central["central<br/><i>control plane</i><br/>Configuration and Central API"]
db[("Postgres<br/>one database<br/>schemas auth, central, edge")]
end
upstream{{"🔌 Upstream APIs"}}
notifications{{"📧 OTP delivery"}}
admin -->|Console and API| proxy
user -->|Login and API calls| proxy
proxy --> edge
proxy --> auth
edge -->|Token, PAR, userinfo| auth
edge -->|Console API calls| central
edge -.->|Sync| central
auth -.->|Sync| central
edge -->|Proxy| upstream
auth -->|Request OTP| notifications
central --> db
auth --> db
edge --> db
style admin fill:#92400e,stroke:#92400e,color:#fff
style user fill:#166534,stroke:#166534,color:#fff
style proxy fill:#334155,stroke:#e6edf3,color:#fff
style central fill:#155e75,stroke:#e6edf3,color:#fff
style edge fill:#155e75,stroke:#e6edf3,color:#fff
style auth fill:#155e75,stroke:#e6edf3,color:#fff
style db fill:#0e4a5c,stroke:#e6edf3,color:#fff
style upstream fill:#334155,stroke:#e6edf3,color:#fff
style notifications fill:#334155,stroke:#e6edf3,color:#fff
style versola fill:#eaf3f5,stroke:#155e75,stroke-width:2px,color:#15171c
Порты
| Порт | Переменная | Что обслуживает |
|---|---|---|
8080 | PORT | API сервиса (auth) |
8081 | DPORT | /metrics, /liveness, /readiness |
8082 | APORT | Внутренний API (auth: настройки аккаунта) |
8083 | MPORT | Listener для mutual TLS у auth и у edge (для /resources), каждый только если настроен его блок mutual-tls |
В серверном развертывании (vps), созданном через CLI, central слушает 8090 (диагностика 8091), edge — 8095 (диагностика 8096), а versola-proxy — 2821. Локальный стек тоже публикует прокси на 127.0.0.1:2821.
Путь запроса
flowchart TB
admin[["👤 Admin<br/><i>Manages platform</i>"]]
user[["👤 End User<br/><i>Accesses apps</i>"]]
versola["⚡ Versola<br/><b>Identity & Authorization Platform</b>"]
upstream{{"🔌 Upstream<br/>Backend APIs"}}
notifications{{"📧 Notification Channel<br/>Notifications"}}
admin -->|Manage| versola
user -->|Auth| versola
versola -->|Proxy| upstream
versola -->|Request Notification| notifications
style admin fill:#92400e,stroke:#92400e,color:#fff
style user fill:#166534,stroke:#166534,color:#fff
style versola fill:#155e75,stroke:#e6edf3,color:#fff,stroke-width:3px
style upstream fill:#334155,stroke:#e6edf3,color:#fff
style notifications fill:#334155,stroke:#e6edf3,color:#fff
Браузерное приложение
- Браузер открывает
GET /login/{presetId}наedge. - Если клиенту нужен PAR,
edgeотправляет запрос авторизации вauth, затем перенаправляет браузер на/authorizeвauthс PKCE иstate. authвыполняет вход пользователя и перенаправляет обратно на/completeвedgeс кодом.edgeобменивает код на токены через/token, сохраняет refresh-токен и устанавливает cookieEDGE_SESSION.- Каждый вызов API идет с этим cookie.
edgeпроверяет токен, применяет политику и проксирует запрос.
sequenceDiagram
autonumber
participant B as Browser
participant E as edge
participant A as auth
participant U as Upstream
B->>E: GET /login/:presetId
E->>A: POST /par (when the client requires PAR)
E-->>B: 302 → auth /authorize (PKCE, state)
note over B,A: Challenge flow (password / OTP / passkey)
A-->>B: 302 → edge /complete?code=…&state=…
B->>E: GET /complete?code=…
E->>A: POST /token (code + PKCE verifier)
A-->>E: access_token + refresh_token
E->>E: Store refresh token in DB
E-->>B: 302 → app + Set-Cookie: EDGE_SESSION
note over B,E: Session active — every request carries the cookie
B->>E: GET /resources/api/v1/data
E->>E: Validate token, check revocation, evaluate CEL rules
E->>U: Forward + inject Authorization header (Basic / Bearer)
U-->>E: 200 OK
E-->>B: 200 OK (upstream Set-Cookie stripped)
Мобильное приложение через edge
У нативного клиента за edge нет собственного клиентского секрета. edge аутентифицируется в auth как клиент по сертификату на listener mTLS, а токены привязывает к ключу DPoP, который хранится на устройстве. Redirect выполняется через App Link, а не через собственную схему URI.
sequenceDiagram
autonumber
participant M as Mobile app
participant E as edge
participant A as auth
participant U as Upstream
M->>E: POST /native/start/{clientId} + DPoP proof (device key)
E->>A: POST /par as the client (PKCE, state, dpop_jkt)
E-->>M: request_uri, sealed blob
note over M,A: System browser opens auth /authorize, user signs in
A-->>M: Redirect to the App Link with code and state
M->>E: POST /native/complete/{clientId} + blob + DPoP proof
E->>A: POST /token (code + PKCE verifier from blob)
A-->>E: DPoP-bound access_token + refresh_token
E-->>M: Token response relayed unchanged
M->>M: Store tokens and device key (Keychain / Keystore)
note over M,E: Session active — app sends DPoP-bound calls
M->>E: GET /resources/api/v1/data + Authorization: DPoP + DPoP proof
E->>E: Check revocation, token binding, permissions and CEL rules
E->>U: Forward + inject Authorization header
U-->>E: 200 OK
E-->>M: 200 OK
note over M,E: Refresh
M->>E: POST /native/token/{clientId} (refresh_token) + DPoP proof
E->>A: POST /token as the client
A-->>E: new tokens
E-->>M: new tokens
Нативное приложение может быть и публичным клиентом, который обращается к auth напрямую, но только в тенанте с профилем standard (профили безопасности).