Skip to main content

tai-keycloak

Keycloak para servicios Python, y las herramientas para levantarlo y desplegarlo.

  • Validar tokens sin hablar con Keycloak: firma contra el JWKS del realm (cacheado, con rotación de claves), emisor, tipo, audiencia y caducidad.
  • Login, refresco y logout en nombre de un usuario.
  • Administrar usuarios, grupos, roles, clientes y el perfil de usuario con un coste conocido por operación, sin N+1.
  • tai-kc: Keycloak de desarrollo con Docker, un realm seguro por defecto y los ficheros para desplegarlo en cualquier orquestador, en Azure u on-premise con Traefik.

Es la pieza de la plataforma tai que usan las APIs que genera tai-api en modo Keycloak, y funciona igual de bien sola.

pip install tai-keycloak

Python 3.10+. El runtime depende de httpx, jwcrypto y pydantic.

En una API

from tai_keycloak import InvalidTokenError, Keycloak, KeycloakSettings

kc = Keycloak(KeycloakSettings.from_env())   # no abre conexiones
realm = kc.realm("main")

async def current_user(authorization: str):
    try:
        claims = await realm.tokens.validate(authorization.removeprefix("Bearer "))
    except InvalidTokenError as error:
        raise HTTPException(401, error.message)
    return claims.preferred_username, claims.client_roles("api")

# al apagar
await kc.aclose()

validate() solo habla con Keycloak la primera vez (descarga el JWKS) y cuando llega un token firmado con una clave nueva; el resto es CPU.

Configuración

Variable Qué es
MAIN_KEYCLOAK_URL URL del servidor (https://auth.example.com, http://localhost:8090, con ruta si la tiene)
KEYCLOAK_API_CLIENT_SECRET Secreto del cliente api: login y cuenta de servicio para administrar
KEYCLOAK_PUBLIC_URL URL con la que los clientes ven Keycloak, si no es la misma (emisor de los tokens)
KEYCLOAK_ADMIN_USERNAME / KEYCLOAK_ADMIN_PASSWORD Administrador de master, solo para gestionar realms
KEYCLOAK_API_CLIENT / KEYCLOAK_APP_CLIENT Nombres de los clientes (por defecto api y app)
KEYCLOAK_VERIFY_SSL, KEYCLOAK_TIMEOUT Verificación del certificado y segundos por petición

No hay credenciales por defecto: si falta algo, el error dice qué definir.

Errores

Toda operación devuelve lo que promete o lanza un TaiKeycloakError con message, solution y status (el código HTTP con el que respondería una API):

Excepción status Cuándo
InvalidTokenError 401 Token caducado, manipulado, de otro emisor, sin la audiencia…
InvalidCredentialsError 401 Usuario o contraseña incorrectos (sin distinguir cuál)
NotFoundError / ConflictError 404 / 409 No existe / ya existe o el nombre es ambiguo
InvalidRequestError 400 Keycloak rechaza los datos (política de contraseñas, perfil…)
PermissionDeniedError 403 A la cuenta de servicio le falta un rol
ServiceAuthenticationError, ConfigurationError 500 Secreto o configuración incorrectos
KeycloakUnavailableError / KeycloakServerError 503 / 502 Keycloak no responde / falla

Administrar

from pydantic import SecretStr
from tai_keycloak import GroupCreate, UserCreate, UserUpdate

await realm.groups.create(GroupCreate(name="operario", client_roles={"api": ["autor-read"]}))
await realm.users.create(UserCreate(username="ana", password=SecretStr("…"), groups=["operario"]))

page = await realm.users.list(group="operario", enabled=True, limit=50)   # items + total
ana = await realm.users.get("ana", effective=True)    # roles efectivos, heredados de sus grupos
await realm.users.update("ana", UserUpdate(password=SecretStr("…")))    # cierra sus sesiones

Lo que conviene saber:

  • Crear es atómico: si un grupo o un rol no existe, el usuario no queda creado.
  • UserUpdate solo toca lo que se indica: attributes se mezcla; grupos y roles son el conjunto final.
  • Cambiar la contraseña o deshabilitar a un usuario cierra todas sus sesiones.
  • Keycloak 26 descarta en silencio los atributos que el perfil no declara; la librería lo detecta y lanza el error. Los atributos de RLS se declaran con realm.profile.set_rls_attributes([...]).

En scripts y notebooks, la misma API bloqueante:

from tai_keycloak.sync import SyncKeycloak

with SyncKeycloak() as kc:
    print(kc.realm("main").users.count())

Y para probar código que valida tokens sin un Keycloak, tai_keycloak.testing.SigningKeys firma tokens como los de Keycloak y sirve su JWKS con un httpx.MockTransport.

tai-kc

tai-kc init --mode development   # keycloak/: Dockerfile, compose, realm seguro, .env con secretos aleatorios
tai-kc run                       # Keycloak en http://localhost:8090
tai-kc check                     # ¿puede tu API hablar con él? dice qué falla y cómo arreglarlo
tai-kc realm new norte           # otro realm
tai-kc api users --group operario
tai-kc stop

Modos de init:

Modo Qué genera
development compose con H2 en un volumen (o PostgreSQL con tai-kc run --db postgres)
production la imagen prod optimizada y las variables que necesita, para cualquier orquestador
azure lo anterior más un workflow de GitHub Actions que construye, sube a ACR y despliega en una Web App
onpremise compose con Traefik (TLS con tus certificados) delante de Keycloak y PostgreSQL externo

Ningún secreto entra en una imagen: contraseñas y secretos se pasan en runtime. El realm generado no tiene redirecciones comodín, protege contra fuerza bruta, exige contraseñas de 12 caracteres, deja nombre y apellidos opcionales y da a la cuenta de servicio de la API solo los roles que necesita. init nunca borra nada, y un .env existente no se pisa ni con --force.

Desarrollo

pip install -e ".[dev]"
pytest                                                         # sin Keycloak: se saltan los de integración
TAI_KEYCLOAK_TEST_URL=http://admin:admin@localhost:8080 pytest # con un Keycloak real

Las reglas de diseño de la librería están en .claude/rules/.

Release files for tai-keycloak 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tai-keycloak 0.3.0
File Size Uploaded
tai_keycloak-0.3.0.tar.gz 68.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tai-keycloak 0.3.0
File Interpreter ABI Platform
tai_keycloak-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 157.4 kB

Release files / tai_keycloak-0.3.0.tar.gz

Download URL tai_keycloak-0.3.0.tar.gz
Size 68.7 kB
Tags Source
SHA-256 checksum
How to use checksums
035ea1d480d535d2c48df9d51b62ae509666d42e458b8c44497d95aa830fb8d3
BLAKE2b-256 checksum
How to use checksums
89cbdc4ec4e89195d6f46598cf6b1c28435752952118e5fdede3d696e6028ff2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.1 CPython/3.12.14 Linux/6.17.0-1022-azure

Release files / tai_keycloak-0.3.0-py3-none-any.whl

Download URL tai_keycloak-0.3.0-py3-none-any.whl
Size 88.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
214a5c25c1615fcedb6f90a0c6a715eeb6e40f3faba732f76ef6f8d4842b6920
BLAKE2b-256 checksum
How to use checksums
b382f75a2132d278243c022023d1b66da5af7f14fe9ecc11505cbfbb82672e00
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.1 CPython/3.12.14 Linux/6.17.0-1022-azure

Release history Release notifications | RSS feed

0.3.1

2 release files

This release

0.3.0 This release

2 release files

0.2.15

2 release files

0.2.11

2 release files

0.2.10

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.20

2 release files

0.1.19

2 release files

0.1.13

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page