Skip to Content
ConfigurationsOIDC & Issuer Trust

OIDC & Issuer Trust

KalamDB supports one external OpenID Connect provider per server process, configured under [auth.oidc].

Use this page when you want the Admin UI, the CLI, or direct bearer-token clients to authenticate through a standards-compliant OIDC issuer such as Dex, Keycloak, Okta, Auth0, Entra ID, Google, or Firebase.

There is no active [oauth] or [oauth.providers.*] matrix anymore. The current model is:

  • [auth.local] for local username/password login
  • [auth.oidc] for one external OIDC provider
  • auth.jwt_trusted_issuers for the issuer allow-list used by bearer-token validation

Token Routing Model

KalamDB inspects every bearer token before signature verification to decide how to validate it:

Token algToken issValidation Path
HS256kalamdbInternal: verified using auth.jwt_secret
RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384Any trusted issuerExternal: verified via OIDC discovery + provider JWKS

ES512 is not supported.

This means external tokens from supported OIDC providers are validated natively through the bearer-token pipeline.

server.toml Settings

TOML
[auth]jwt_secret = "replace-with-strong-random-secret-32-plus-chars"jwt_trusted_issuers = "kalamdb,https://issuer.example.com"jwt_expiry_hours = 24allow_remote_setup = falsecookie_secure = true [auth.local]enabled = true [auth.oidc]enabled = truedisplay_name = "Company SSO"issuer = "https://issuer.example.com"client_id = "kalamdb"client_secret = "optional-confidential-client-secret"scopes = ["openid", "email", "profile"]auto_provision = truedefault_role = "user"broker_device_flow_enabled = true# Optional override when discovery metadata omits device flow.device_authorization_endpoint = "https://issuer.example.com/oauth2/device_authorization"# Optional explicit audience override. Defaults to client_id when unset.# audience = "kalamdb-api"

Notes:

  • [auth] is the canonical section name. [authentication] still deserializes as a compatibility alias for local files, but new docs and examples use [auth].
  • auth.oidc.issuer and auth.oidc.client_id are required when auth.oidc.enabled = true.
  • auth.oidc.scopes must include openid.
  • auth.oidc.audience is optional and defaults to client_id when omitted.
  • jwt_trusted_issuers is a comma-separated string, not an array.
  • Keep kalamdb in jwt_trusted_issuers so local KalamDB-issued tokens continue to verify.
  • Legacy [oauth] and [oauth.providers.*] sections are no longer supported.

Environment Variable Overrides

BASH
export KALAMDB_JWT_SECRET="replace-with-strong-random-secret-32-plus-chars"export KALAMDB_JWT_TRUSTED_ISSUERS="kalamdb,https://issuer.example.com"export KALAMDB_AUTH_LOCAL_ENABLED=trueexport KALAMDB_AUTH_OIDC_ENABLED=trueexport KALAMDB_AUTH_OIDC_DISPLAY_NAME="Company SSO"export KALAMDB_AUTH_OIDC_ISSUER="https://issuer.example.com"export KALAMDB_AUTH_OIDC_CLIENT_ID="kalamdb"export KALAMDB_AUTH_OIDC_CLIENT_SECRET="optional-confidential-client-secret"export KALAMDB_AUTH_OIDC_SCOPES="openid,email,profile"export KALAMDB_AUTH_OIDC_AUTO_PROVISION=trueexport KALAMDB_AUTH_OIDC_DEFAULT_ROLE="user"export KALAMDB_AUTH_OIDC_BROKER_DEVICE_FLOW_ENABLED=true

Boolean env vars accept "true", "1", or "yes" (case-insensitive).

Environment variables override server.toml values.

OIDC Configuration Matrix

server.toml keyEnvironment variableRequired when OIDC enabledNotes
auth.jwt_secretKALAMDB_JWT_SECRETYesUsed for KalamDB-issued HS256 access and refresh tokens
auth.jwt_trusted_issuersKALAMDB_JWT_TRUSTED_ISSUERSYesInclude kalamdb plus the configured OIDC issuer
auth.local.enabledKALAMDB_AUTH_LOCAL_ENABLEDNoDisable local username/password auth after OIDC migration if desired
auth.local.bcrypt_costNoPassword hash work factor for local users
auth.local.min_password_lengthNoMinimum accepted local password length
auth.local.max_password_lengthNoMaximum accepted local password length
auth.local.enforce_password_complexityNoRequire uppercase, lowercase, digit, and special characters
auth.oidc.enabledKALAMDB_AUTH_OIDC_ENABLEDYesEnables the single external OIDC provider
auth.oidc.display_nameKALAMDB_AUTH_OIDC_DISPLAY_NAMENoHuman-facing label in UI/CLI, for example Dex or Company SSO
auth.oidc.issuerKALAMDB_AUTH_OIDC_ISSUERYesMust start with http:// or https://
auth.oidc.client_idKALAMDB_AUTH_OIDC_CLIENT_IDYesUsed for browser and device flows and default audience validation
auth.oidc.client_secretKALAMDB_AUTH_OIDC_CLIENT_SECRETNoNeeded for confidential clients or some brokered device flows
auth.oidc.scopesKALAMDB_AUTH_OIDC_SCOPESNoCSV env value; must include openid
auth.oidc.device_authorization_endpointKALAMDB_AUTH_OIDC_DEVICE_AUTHORIZATION_ENDPOINTNoOptional override when discovery omits device flow
auth.oidc.broker_device_flow_enabledKALAMDB_AUTH_OIDC_BROKER_DEVICE_FLOW_ENABLEDNoEnables KalamDB-brokered device flow endpoints
auth.oidc.auto_provisionKALAMDB_AUTH_OIDC_AUTO_PROVISIONNoAllows absent regular OIDC subjects when default role is user; creates rows for elevated default roles
auth.oidc.default_roleKALAMDB_AUTH_OIDC_DEFAULT_ROLENoDefault role for auto-provisioned users
auth.oidc.audienceKALAMDB_AUTH_OIDC_AUDIENCENoExplicit audience override; defaults to client_id

Browser And Device Endpoints

Clients discover the current auth surface from:

TEXT
GET /v1/api/auth/login-options

KalamDB exposes these OIDC-facing endpoints:

EndpointUsed byPurpose
POST /v1/api/auth/oidc/exchange-codeAdmin UI and CLI browser loginExchange authorization code and PKCE verifier for KalamDB tokens
POST /v1/api/auth/oidc/exchange-tokenCLI direct device loginExchange provider ID token for KalamDB tokens
POST /v1/api/auth/oidc/device/startCLI brokered device loginStart KalamDB-brokered device flow
POST /v1/api/auth/oidc/device/pollCLI brokered device loginPoll for brokered device completion

Redirect URIs to register at the provider:

  • Admin UI: https://YOUR_KALAMDB_ORIGIN/ui/oauth/callback
  • CLI browser login: http://127.0.0.1:8787/callback

OIDC Discovery Flow

When KalamDB encounters an external token (non-HS256):

  1. Extracts alg and kid from the JWT header (unverified).
  2. Extracts iss from the JWT payload (unverified).
  3. Confirms iss is in jwt_trusted_issuers.
  4. Fetches {issuer_url}/.well-known/openid-configuration.
  5. Extracts jwks_uri from the discovery response.
  6. Fetches the JWKS endpoint and caches keys by kid.
  7. Matches the token kid to a cached signing key.
  8. Validates signature, issuer, expiry, and audience (if configured).

JWKS Caching Behavior

  • Keys are cached per-issuer in memory, indexed by kid.
  • Cache-miss refresh: if a token’s kid is not found, KalamDB automatically re-fetches the JWKS endpoint.
  • No TTL-based eviction: cache refreshes only on miss — keys remain cached until an unknown kid triggers a refresh.
  • Keys without a kid field are silently discarded from the cache.
  • Key rotation at the provider is handled automatically (new kid → cache miss → refresh).

JWT Claims Structure

KalamDB reads these claims from external tokens:

ClaimTypeRequiredNotes
substringYesKalamDB user_id; must be a valid UserId
issstringYesMust match a trusted issuer
expnumberYesExpiry (Unix timestamp, seconds)
iatnumberYesIssued-at (Unix timestamp, seconds)
username / preferred_usernamestringNoInformational only; not used as the KalamDB user_id
emailstringNoUser email
rolestringNoKalamDB role: user, service, dba, system
token_typestringNo"access" or "refresh"

Deployment Checklist

  1. Confirm the exact issuer URL. Trailing slashes matter.
  2. Register the Admin UI and CLI redirect URIs at the provider.
  3. Set auth.oidc.issuer, auth.oidc.client_id, and auth.jwt_trusted_issuers.
  4. Keep auth.local.enabled = true during bootstrap and migration.
  5. Test GET /v1/api/auth/login-options.
  6. Test Admin UI browser login and at least one CLI OIDC mode.
  7. Disable local auth later only after OIDC access is verified.

Troubleshooting

SymptomLikely CauseFix
401 Unauthorized on external tokenIssuer not in jwt_trusted_issuersAdd exact issuer URL
auth.oidc.issuer is required on startupOIDC enabled without issuerSet auth.oidc.issuer
auth.oidc.client_id is required on startupOIDC enabled without client IDSet auth.oidc.client_id
auth.oidc.scopes must include the 'openid' scopeMissing required scopeAdd openid to auth.oidc.scopes
MissingKid errorToken missing kid headerProvider must include kid in JWT header
KeyNotFound after JWKS refreshKey rotated and kid no longer presentCheck provider JWKS, ensure key is published
DiscoveryFailedCannot reach /.well-known/openid-configurationCheck network, DNS, and issuer URL format
JwtValidationFailed: ExpiredSignatureToken expiredGet fresh token from provider
User not found after authauth.oidc.auto_provision is false or elevated roles are explicitEnable auto-provision or pre-create the user with CREATE USER '<sub>' WITH OIDC ...
Last updated on