This module implements a simple OAuth 2.0 token validator for built-in support of the Device Authorization Flow. The validator performs minimal validation by:
- Extracting the
sub(subject) andscopefields from the JWT payload. - Comparing the token's scopes with those required by the
pg_hba.confentry. - Mapping the authenticataion identity
subto a database role usingpg_ident.conf. - Allowing or denying access based on matching of sub and scope.
- PostgreSQL >= 18 configured with
--with-libcurlflag
- Compile and install the validator dynamic library.
For this run the following commands in the main directory:
make
make installValidator will be installed in the <postgres>/lib directory under filename oauth_validator.so
- Add the validator in the
postgresql.confto the settingoauth_validator_libraries:
oauth_validator_libraries='oauth_validator'
- Configure the config file
pg_ident.conf
For example:
# MAPNAME SYSTEM-USERNAME PG-USERNAME
oauthmap "7cf5b11f-adb2-4e67-83b7-5c75f7f1e6ee" "mydbuser"
- Configure the config file
pg_hba.conf
For example:
local all all oauth issuer="https://<address>/.well-known/openid-configuration" scope="openid postgres" map="oauthmap"
posgtresql.confmust contain validator module inoauth_validator_librariesentrypg_hba.confmust specifyoauthas the authentication method and defineoauth_scopepg_ident.confmust contain mappings between JWT sub values and PostgreSQL roles.
# MAPNAME SYSTEM-USERNAME PG-USERNAME
oauthmap "7cf5b11f-adb2-4e67-83b7-5c75f7f1e6ee" "mydbuser"
If the token contains sub value "7cf5b11f-adb2-4e67-83b7-5c75f7f1e6ee", and validation passes, PostgreSQL will map "7cf5b11f-adb2-4e67-83b7-5c75f7f1e6ee" to the mydbuser role using the oauthmap entry.
local all all oauth issuer="https://<address>/.well-known/openid-configuration" scope="openid postgres" map="oauthmap"
The core validation logic is implemented through the validate_token function. It performs the following steps:
-
Parsing the token payload The raw token string is parsed to extract its payload. If the token is malformed or the payload cannot be extracted, validation fails.
-
Extracting JWT claims:
subandscopeThe payload must contain both:sub: Subject (used to identify the user)scope: Space-separated list of scopes granted by the token
If either field is missing, validation fails.
-
Comparing scopes The scopes from the entry
oauth_scopeinpg_hba.confare compared with the scopes granted by the token. If some are missing in the token, validation fails.In the above configs example, validation is succesfull if the token contains both
openidandpostgresscopes. -
Setting authorization result The
res->authorizedflag is set totrueif scopes match, otherwisefalse. -
Assigning authentication identity The
subvalue is assigned tores->authn_id, which PostgreSQL uses to identify the authenticated user. -
Assigning authentication identity This
subvalue is then matched outside of this module against entries inpg_ident.confto determine the actual database role the user is allowed to assume.If matching fails, validation fails.
-
Otherwise validation is succesfull and the client is authorized and succesfully connected to the database.
This basic implementation can be extended with additional checks or custom logic, such as:
- Validating token signatures
- Validating token expiration (
exp) - Validating audience (
aud) or issuer (iss) - Fetching user roles dynamically