keycloak-sso-gateway
Ready-to-run OIDC / Keycloak callback server for a fleet of Telegram
bots and domain web apps. One public HTTPS origin; configure targets via env
and deploy with Docker Compose (or python -m keycloak_sso_gateway).
Companion bot adapter:
aiogram-keycloak-sso
(GitHub) —
bots never expose HTTP; this gateway owns /sso/callback. Wire DTOs
(SSOSession, login events, Redis prefixes) are duplicated in both packages
and must stay in sync (schema_version).
Install
pip install "keycloak-sso-gateway[redis]"
# or without Redis extras if you only need the library pieces:
pip install keycloak-sso-gateway
Import package name (underscore): keycloak_sso_gateway.
CLI entry points:
keycloak-sso-gateway
# same as:
python -m keycloak_sso_gateway
Local run
cp .env.example .env # fill SSO_* / GATEWAY_* / REDIS_URL
pip install -e ".[redis]"
python -m keycloak_sso_gateway
main() auto-loads .env from the current working directory (or the path in
SSO_ENV_FILE). Existing process environment variables are never overwritten.
Missing file → no-op.
Docker Compose
Host port 8091 → container 8080. Shared network name: sso-fleet.
cp .env.example .env # fill SSO_* / GATEWAY_*
docker network create sso-fleet # once
docker compose up -d --build
# local: http://localhost:8091/sso/callback
Compose still uses env_file: .env and overrides REDIS_URL / PORT for the
container. PUBLIC_CALLBACK_URL must be the public HTTPS URL registered in
Keycloak (edge TLS in front of :8091), not the container-local address.
Public URLs
| Method | Path | Purpose |
|---|---|---|
GET |
/sso/login |
Start web login (app_id, return_uri, optional next) → 302 to Keycloak |
GET |
/sso/callback |
Keycloak redirect (code + state) — single fleet redirect_uri |
POST |
/sso/handoff |
Web app redeems one-shot handoff: {"handoff":"..."} → tokens JSON |
Bots never call /sso/login; they build the authorize URL themselves (via
aiogram-keycloak-sso) and only need this gateway as the shared callback +
Redis session/event bus.
Modes
Bot (shared Redis)
- Bot builds authorize URL with
state=bot:<bot_id>:<hmac>(legacy<bot_id>:<hmac>still accepted). - Keycloak redirects to
/sso/callback. - Gateway exchanges the code, writes the session to Redis, publishes a login
event, redirects to
t.me/...or shows success HTML.
Web (one-shot handoff)
- Browser (or web backend redirect) hits
GET /sso/login?app_id=portal&return_uri=https://app.example.com/sso/complete&next=/dashboard
(return_urimust be allowlisted inGATEWAY_WEB_APPS). - Gateway 302 → Keycloak; Keycloak returns to the same
/sso/callback. - Gateway stores tokens under a handoff id (TTL ~120s) and
302toreturn_uri?handoff=.... - Web backend
POST /sso/handoffonce, gets tokens + claims, sets its own cookie/session.
Web apps do not poll Redis bot sessions.
Environment
| Variable | Role |
|---|---|
PORT |
Listen port (default 8080) |
REDIS_URL |
Redis for sessions, events, handoffs |
PUBLIC_CALLBACK_URL |
Fleet-wide OIDC redirect_uri |
SSO_ISSUER / SSO_CLIENT_ID / SSO_CLIENT_SECRET |
One confidential Keycloak client |
SSO_STATE_SECRET |
HMAC base secret (namespaced per bot/app id) |
GATEWAY_BOT_IDS |
Comma-separated bot ids |
GATEWAY_WEB_APPS |
Web app allowlist (see below) |
POST_LOGIN_REDIRECT_TEMPLATE |
Optional https://t.me/{bot_id}_bot; unset → HTML success page |
SSO_ENV_FILE |
Optional dotenv path (default .env in cwd) |
GATEWAY_WEB_APPS
app_id=https://app.example.com/sso/complete;crm=https://crm.example.com/done,https://crm.example.com/dev
;separates apps,separates allowlistedreturn_urivalues for one app- empty / unset → bots only
Wire contract
Redis key prefixes and JSON shapes (SSOSession, login events, handoff
payload, schema_version) are the shared bus contract with bot processes
(aiogram-keycloak-sso). Keep them in sync with consumers.
Development
pip install -e ".[dev,redis]"
pytest
Optional smoke helpers live under integration/ when present.
Metadata
Release files for keycloak-sso-gateway 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| keycloak_sso_gateway-0.1.0.tar.gz | 45.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| keycloak_sso_gateway-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 85.8 kB
Release files / keycloak_sso_gateway-0.1.0.tar.gz
| Download URL | keycloak_sso_gateway-0.1.0.tar.gz |
|---|---|
| Size | 45.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fdf35dfc10c8e1162fec39bae337b444c002be41dd9948e8f4f59f6c7bac8dd2
|
|
BLAKE2b-256 checksum How to use checksums |
4a8359b8350ca8b53e49457fa7a9b153feeb916e6a3951b1c695122a781345ae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / keycloak_sso_gateway-0.1.0-py3-none-any.whl
| Download URL | keycloak_sso_gateway-0.1.0-py3-none-any.whl |
|---|---|
| Size | 39.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ec167a55764b9b9c0aff656272a06da62f561fe768a53478dd8a1833bd48709
|
|
BLAKE2b-256 checksum How to use checksums |
fed1a277897ebc4de884064c5f3e0857ebe26d3c67a2792f7cb44eddbf8d46e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|