Keycloak
KalamDB natively validates Keycloak RS256 tokens via OIDC discovery — no bridge service required.
Integration Model
KalamDB bearer token validation routes by algorithm:
- HS256 with
iss = "kalamdb"→ internal shared-secret validation. - RS256 / ES256 / etc. from a trusted issuer → external OIDC discovery + JWKS validation.
Keycloak issues RS256 tokens by default, so KalamDB validates them directly when the issuer is trusted.
Supported algorithms: RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384. ES512 is not supported.
Quick Start with Docker Compose
The KalamDB repository includes a Keycloak service in docker/utils/docker-compose.yml:
keycloak:
image: quay.io/keycloak/keycloak:26.0
command: ["start-dev", "--import-realm"]
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
ports:
- "8081:8080"
volumes:
- ./keycloak/realm-import:/opt/keycloak/data/import:ro
- ./keycloak/data:/opt/keycloak/dataStart it:
docker compose up keycloak -dAdmin console: http://127.0.0.1:8081
Default credentials: admin / admin
Configure KalamDB
Step 1: Add Keycloak as a trusted issuer
The issuer URL format for Keycloak is https://<host>/realms/<realm>:
[authentication]
jwt_trusted_issuers = "http://127.0.0.1:8081/realms/myrealm"
auto_create_users_from_provider = trueOr via environment variables:
export KALAMDB_JWT_TRUSTED_ISSUERS="http://127.0.0.1:8081/realms/myrealm"
export KALAMDB_AUTH_AUTO_CREATE_USERS_FROM_PROVIDER=trueTo keep internal login working alongside Keycloak:
export KALAMDB_JWT_TRUSTED_ISSUERS="kalamdb,http://127.0.0.1:8081/realms/myrealm"Step 2: Create a Keycloak client
In the Keycloak Admin Console:
- Select your realm (or create one).
- Go to Clients → Create client.
- Set Client ID (e.g.,
kalamdb-app). - Set Client authentication to
Onif using confidential clients;Offfor public clients. - Under Valid redirect URIs, add your app URL.
- Note the Client ID — this is used for audience validation.
Step 3: Create a user in Keycloak
- Go to Users → Add user.
- Set username (e.g.,
alice). - Under Credentials, set a password.
- Enable the user.
Step 4: Get a token and use it
# Get token via direct-access grant (for testing)
KC_TOKEN=$(curl -s -X POST \
http://127.0.0.1:8081/realms/myrealm/protocol/openid-connect/token \
-d "client_id=kalamdb-app&grant_type=password&username=alice&password=secret" \
| jq -r .access_token)
# Use it with KalamDB
curl -X POST http://127.0.0.1:8080/v1/api/sql \
-H "Authorization: Bearer $KC_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"sql":"SELECT CURRENT_USER();"}'How Validation Works
- KalamDB receives the Keycloak RS256 token.
- Extracts
iss(e.g.,http://127.0.0.1:8081/realms/myrealm) and confirms it is trusted. - Fetches
{iss}/.well-known/openid-configurationto discover thejwks_uri. - Fetches the JWKS endpoint and caches keys by
kid. - Validates signature, issuer, and expiry.
- Maps
preferred_username(Keycloak default) to KalamDB username.
JWKS Caching
- Keys are cached per-issuer in memory.
- Unknown
kid→ automatic JWKS refresh. - No TTL-based eviction — keys remain until a cache miss triggers refresh.
- Keycloak key rotation is handled transparently.
Issuer URL Precision
The issuer URL must exactly match the iss claim in Keycloak tokens:
| Correct | Incorrect |
|---|---|
http://127.0.0.1:8081/realms/myrealm | http://127.0.0.1:8081/realms/myrealm/ (trailing slash) |
https://keycloak.example.com/realms/prod | https://keycloak.example.com/ (missing realm) |
Check the token iss claim: echo $KC_TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | jq .iss
Verification Checklist
- Confirm Keycloak realm issuer URL matches the token
issclaim exactly. - Add issuer to
jwt_trusted_issuers. - Restart KalamDB.
- Get a Keycloak token using direct-access grant or browser flow.
- Send it as
Authorization: Bearer <token>to a KalamDB endpoint. - Verify
SELECT CURRENT_USER()returns the expected username.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
401 Unauthorized | Issuer not trusted | Add exact issuer URL to jwt_trusted_issuers |
DiscoveryFailed | KalamDB cannot reach Keycloak | Check network/DNS, ensure /.well-known/openid-configuration is accessible |
| Wrong username | Keycloak sends preferred_username, not username | Both are accepted by KalamDB via serde alias |
| User not found | auto_create_users_from_provider is false | Enable it, or pre-create the user with CREATE USER ... WITH OAUTH |