percona / percona/pg_oidc_validator
The JWT `aud` claim is not validated, so a token minted for another service is accepted
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 36
- Forks
- 15
- PR merge metrics
- No merged PRs in 30d
Description
Summary
configure_verifier_with_jwks() in src/jwk.cpp builds the verifier with an issuer check only:
auto verifier = jwt::verify().with_issuer(expected_issuer);
There is no with_audience() call anywhere, and no setting that could supply an expected audience.
Why this is a security property rather than a feature request
PostgreSQL 18 delegates the whole of token validation to the validator module. The issuer and
scope values on the HBA line are used to build the discovery document the server advertises to
clients; the server never decodes the token, so it checks neither the signature nor exp, iss or
aud. The validator is the only thing between a bearer token and a session.
The upstream design notes say so explicitly, and name audience among the claims a validator is
expected to check:
Implementations must follow the provider's instructions to the letter, including any verification of
issuer ("where is this token from?"), audience ("who is this token for?"), and validity period
("when can this token be used?").
An issuer normally fronts many services, and aud is the claim that says which one a token is for.
Without the check, a token a user legitimately obtained for any other client of the same issuer is a
valid PostgreSQL login as that user — so a low-value application sharing the provider becomes a path
to the database. This is audience confusion, the thing audience restriction exists to prevent.
Proposed shape
pg_hba.conf has no audience option and a validator module cannot add one, so a GUC is the only
place this can live:
- Add
pg_oidc_validator.audience(string,PGC_SIGHUP, default empty). - When set, pass it to
with_audience(), so a mismatched or absentaudfails the login. jwt-cpp
accepts either a stringaudor an array containing the value, which is the RFC 7519 shape. - When unset, behave exactly as today, and write one line to the server log per authentication saying
audis not being validated.
Defaulting to off.
I also tasked my clanker to provide a PR alongside. But happy to discuss it here on the issue first.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/jwk.cpp at configure_verifier_with_jwks() and trace how verifier settings and configuration values are registered. Confirm how the proposed pg_oidc_validator.audience GUC should reach verifier construction, including unset behavior and logging. Done means configured audience mismatches or missing claims are rejected while the empty setting preserves current behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, postgresql
- Domain
- authentication, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100