Categories: | credativ® Inside PostgreSQL® |
---|---|
Tags: | OAuth2 PostgreSQL® |
I created a new project directory and started experimenting.
The goal was to set up PostgreSQL 18 Beta with OAuth2 authentication, and for the identity provider, I chose Keycloak.
I decided to use Docker Compose to quickly and easily spin up both services.
Here is the docker-compose.yml
, that I used:
services:
mock-oauth2:
image: quay.io/keycloak/keycloak:24.0
command: start --https-port=8080 --https-key-store-file=/etc/x509/https/localhost.p12 --https-key-store-password=changeit --import-realm --hostname-strict=false --hostname-url=https://mock-oauth2:8080
ports:
- "8080:8080"
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
volumes:
- ./certs:/etc/x509/https
- ./keycloak-realm.json:/opt/keycloak/data/import/realm.json
networks:
- pgnet
postgres18:
build: .
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: postgres
volumes:
- ./postgres/postgresql.conf:/etc/postgresql/postgresql.conf
- ./postgres/pg_hba.conf:/etc/postgresql/pg_hba.conf
command: ["-c", "config_file=/etc/postgresql/postgresql.conf"]
networks:
- pgnet
networks:
pgnet:
driver: bridge
PostgreSQL expects a connection to the OAuth2 issuer over HTTPS. The same URL must also be reachable from the host, for example, when using the Keycloak UI.
This means: The certificate must be valid and trusted on both the host and in the container.
The hostname used (e.g., https://mock-oauth2:8080
) must be correctly resolvable in both environments.
For this, I added the following line to my /etc/hosts
file on the host:
127.0.0.1 mock-oauth2
This allowed both the PostgreSQL container and my host to reach the Keycloak service at https://mock-oauth2:8080
reach.
Keycloak absolutely requires an HTTPS endpoint for the OAuth2 issuer URL to be accepted by PostgreSQL.
For this, I created a self-signed certificate and converted it into a .p12
-keystore package that Keycloak can use.
The .p12
certificate is mounted into the container via the following mount:
volumes:
- ./certs:/etc/x509/https
In the certs
directory, the file localhost.p12
, which I created from my self-signed key and certificate as follows:
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout server.key \
-out server.crt \
-subj "/CN=mock-oauth2" \
-addext "subjectAltName = DNS:mock-oauth2,DNS:localhost,IP:127.0.0.1"
I created a minimalist realm file for Keycloak. It contains a client named postgres
and a user with corresponding credentials.
Content of keycloak-realm.json
:
{
"realm": "pg",
"enabled": true,
"clients": [
{
"clientId": "postgres",
"enabled": true,
"publicClient": false,
"redirectUris": ["*"],
"protocol": "openid-connect",
"secret": "postgres",
"directAccessGrantsEnabled": true,
"standardFlowEnabled": true
}
],
"users": [
{
"username": "postgres",
"enabled": true,
"credentials": [
{
"type": "password",
"value": "postgres"
}
]
}
]
}
After importing the realm, Keycloak was ready and the default scope was visible in the UI.
libpq-oauth
and oauth_validator
I had to extend the official PostgreSQL image to install additional dependencies such as the extension libpq-oauth
as well as the validator oauth_validator
to install.
PostgreSQL 18 experimentally supports OAuth2 authentication. However, PostgreSQL does not include its own validator library. In the official documentation, it states:
The PostgreSQL distribution does not include any libraries for
OAuth2 token validation. Users must provide their own solution
or compile it themselves.
PostgreSQL
Docs –oauth_validator_libraries
For testing, I used the following open-source implementation:
This minimalist C library can be compiled and used as oauth_validator_library
in PostgreSQL.
FROM postgres:18beta1
USER root
RUN apt-get update \
&& apt-get install -y libpq-oauth build-essential libkrb5-dev \
libsasl2-dev libcurl4-openssl-dev postgresql-server-dev-18 git \
&& git clone https://github.com/TantorLabs/oauth_validator.git /tmp/oauth_validator \
&& cd /tmp/oauth_validator \
&& make && make install \
&& rm -rf /tmp/oauth_validator \
&& apt-get remove -y build-essential git \
&& apt-get autoremove -y && rm -rf /var/lib/apt/lists/*
I then used this image for the `postgres18` service in my Docker Compose setup.
PostgreSQL must trust the certificate presented by Keycloak, otherwise the connection to the OAuth2 issuer will be rejected.
For this, I copied the `mock-oauth.crt` file into the PostgreSQL container and placed it in the typical CA path:
/usr/local/share/ca-certificates/
Then, inside the container, I executed the following command:
update-ca-certificates
After that, the certificate was accepted and PostgreSQL could successfully verify the connection to the HTTPS issuer.
In pg_hba.conf
, I added the following line:
host all all all oauth scope="profile" issuer="https://mock-oauth2:8080/realms/pg" map="oauthmap"
In pg_ident.conf
, I mapped the identity provided by the token to the PostgreSQL user:
oauthmap "postgresID" "postgres"
This mapping may need to be adjusted – depending on how your Keycloak client is configured and which field (e.g.,preferred_username
or sub
) is passed in the token.
To test the connection, I used the following `psql` command:
psql "host=localhost \
port=5432 \
dbname=postgres \
user=postgres \
oauth_issuer=https://mock-oauth2:8080/realms/pg \
oauth_client_id=postgres \
oauth_client_secret=changeme \
oauth_scope=profile"
After the call, a device code message appears, such as:
Visit `https://mock-oauth2:8080/realms/pg/device` and enter
the code FBAD-XXYZ.
After logging in with the user credentials, `psql` successfully establishes a connection to PostgreSQL via OAuth2.
pg_hba.conf
is sensitive to formatting errors. I had to reload the configuration multiple times (SELECT pg_reload_conf();
) and carefullyanalyze the logs..crt
certificate into the container and register it with update-ca-certificates
.This was an exciting, practical experiment with a promising new feature in PostgreSQL. OAuth2 integration brings PostgreSQL closer to modern identity management solutions and simplifies operation in environments with centralized authentication.
Categories: | credativ® Inside PostgreSQL® |
---|---|
Tags: | OAuth2 PostgreSQL® |
You need to load content from reCAPTCHA to submit the form. Please note that doing so will share data with third-party providers.
More InformationYou are currently viewing a placeholder content from Brevo. To access the actual content, click the button below. Please note that doing so will share data with third-party providers.
More InformationYou need to load content from reCAPTCHA to submit the form. Please note that doing so will share data with third-party providers.
More InformationYou need to load content from Turnstile to submit the form. Please note that doing so will share data with third-party providers.
More InformationYou need to load content from reCAPTCHA to submit the form. Please note that doing so will share data with third-party providers.
More InformationYou are currently viewing a placeholder content from Turnstile. To access the actual content, click the button below. Please note that doing so will share data with third-party providers.
More Information