EXPERIMENTAL
Requires: PostgreSQL 18+
This module enables PostgreSQL 18 to delegate authorization decisions to Keycloak using OAuth tokens, leveraging Keycloak Authorization Services for fine-grained, token-based access control.
It sends a permission request to Keycloak's token endpoint using grant_type=urn:ietf:params:oauth:grant-type:uma-ticket and expects a decision response (response_mode=decision), which is a Keycloak-specific extension.
It is designed for use with CloudNativePG, allowing database role elevation to be controlled by Keycloak policies.
- Keycloak-based authorization for PostgreSQL roles
- Delegates database role elevation decisions to Keycloak Authorization Services using OAuth tokens.
 
 - Permission string construction
- Builds permission strings as 
<resource_name>#<scope>and sends permission requests to Keycloak's token endpoint (grant_type=urn:ietf:params:oauth:grant-type:uma-ticket,response_mode=decision). 
 - Builds permission strings as 
 - Configurable via PostgreSQL GUC parameters
- All integration settings (endpoints, resource names, timeouts, debug, etc.) are controlled via GUCs.
 
 - Secure HTTP communication
- Uses libcurl for HTTP requests with configurable timeouts and safe logging.
 
 - Optional JWT issuer verification
- Can verify the 
issclaim in JWT tokens for additional security. 
 - Can verify the 
 
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pg-oauth
spec:
  imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie
  instances: 1
  postgresql:
    extensions:
      - name: keycloak-oauth-validator
        ld_library_path:
          - system
        image:
          reference: ghcr.io/cloudnative-pg/postgres-keycloak-oauth-validator-testing:18-dev-trixie
    parameters:
      oauth_validator_libraries: "kc_validator"
      kc.token_endpoint: "https://<keycloak>/realms/<realm>/protocol/openid-connect/token"
      kc.audience: "postgres-resource"
      kc.resource_name: "appdb"       # Resource name in Keycloak
      kc.client_id: "postgres-resource"
      kc.http_timeout_ms: "2000"
      kc.expected_issuer: "https://<keycloak>/realms/<realm>"
      kc.debug: "on"
      kc.log_body: "on"
      log_min_messages: "debug1"
    pg_hba:
      - host all all 0.0.0.0/0 oauth issuer="https://<keycloak>/realms/<realm>" scope=db_access validator="kc_validator" delegate_ident_mapping=1For a full example, see examples/cnpg/cluster.yaml.
- 
Realm Create or use an existing realm (e.g.,
demo). - 
Resource Server Client (
kc.audience) Create a client for Authorization Services (e.g.,postgres-resource). Enable Authorization Services and add scopes as needed (e.g.,app_readonly,app_readwrite). - 
Validator Client (
kc.client_id) A client allowed to call the token endpoint for permission decisions. - 
Resource & Permission Resource name:
<kc.resource_name>(e.g.,appdb). Scope name:<scope>(e.g.,app_readonly,app_readwrite). Permission name:<resource_name>#<scope>(e.g.,appdb#app_readonly). Create a permission for each database role you want to allow (e.g., DB roleapp_readonlymaps to Keycloak scopeapp_readonly, permission nameappdb#app_readonly). - 
Policies Attach policies to permissions so that only intended users can access specific scopes.
 - 
Issuer Verification (optional) Set
kc.expected_issuerto your realm's issuer URL (e.g.,https://<keycloak>/realms/<realm>). 
You can quickly test the validator using Keycloak's Device Flow and psql:
- 
Connect to PostgreSQL using psql with OAuth parameters:
psql "host=<keycloak> \ user=app_readonly \ dbname=appdb \ oauth_issuer=https://<keycloak>/realms/demo \ oauth_client_id=appA \ oauth_client_secret=<client secret> \ oauth_scope='db_access'"
When you run this command, psql will display a Device Authorization URL and a device code.
 - 
Authenticate via browser:
- Open the displayed URL in your browser.
 - Enter the device code shown by psql.
 - Log in with your Keycloak username and password.
 
Once authentication is complete, psql will automatically obtain an access token and connect to the database.
 
Note: The DB role (
app_readonly) should match the Keycloak scope name. The validator will request permission<resource_name>#<scope>(e.g.,appdb#app_readonly) from Keycloak Authorization Services.
To compile the extension is required meson tool.
meson setup build
meson compile -C buildThe extension will be located inside the build/ directory, that was
created during the setup process.
A simple possibility is to build the image using a plain docker build command:
docker build -t pg-kc-validator -f docker/Dockerfile .To have all the possible labels, annotations, SBOMS, etc. the image can be built using Docker Bake:
docker buildx bake- Do not use self-signed certificates (server.crt) in production; always use a trusted CA.
 - Enable 
kc.log_bodyonly for debugging; keep itoffin production. - Place CA certificates in 
/usr/local/share/ca-certificates/and runupdate-ca-certificatesin your Docker image. 
Apache-2.0. See LICENSE.
