Subject: Custom oauth validator options

From: Zsolt Parragi <[email-masked]>
Date: Tue, 2 Dec 2025 13:05:49 +0000

Hello hackers,

The current OAuth code allows validators to add custom validation
logic, but does not allow them to introduce custom
authentication-related parameters in the place where they belong:
pg_hba.conf. As a workaround, both pg_oidc_validator and
postgres-keycloak-oauth-validator (and likely others; these are simply
the two I know of) rely on GUC variables instead.

I see two issues with this:

1. Configuration for OAuth validation ends up split across two
locations: issuer/scope and a few other parameters are defined in
pg_hba.conf, while custom parameters must be set in postgresql.conf.

2. We have received multiple questions asking how to configure
multiple OIDC servers with different parameter sets. I am not sure how
common it is to use multiple OAuth providers with a single PostgreSQL
instance, but the question is certainly reasonable.

Given this, I would like to ask what you think about making
pg_hba.conf extensible. At present, option parsing is hardcoded in
parse_hba_auth_opt, and any unknown parameter triggers an error at the
end of the function.

I can see a few possible approaches:

a. Add an OAuth-specific hook that allows injecting additional
option-parsing logic into this function, as part of the existing
OAuthValidatorCallbacks. This could be scoped to the validator used on
the specific HBA line, even if multiple validators are loaded.
b. Allow the existing startup callback to supply a list of additional
valid configuration names, with the validation callback responsible
for parsing and validating them.
c. Add a more generic hook usable by any extension. I do not currently
have concrete use cases outside OAuth, but perhaps others do.

I would be interested in your thoughts on whether an improvement in
this area would be useful.

I also have two related questions, which might be addressed as part of
the above or independently:

1. HBA options are parsed sequentially. If validator-specific options
are tied to a particular validator, this implies that validator=...
must appear before its parameters when multiple validators are loaded,
since we cannot otherwise determine which validator is used. Is this
acceptable behavior, or should options be allowed in any order?

2. If a validator introduces many options, an HBA line could become
very long and hard to read. Would it make sense to allow loading the
parameters for a given line from a separate file? This might already
be useful today: for example, if a long issuer URL is repeated across
several HBA lines, it could instead be defined once in an external
file and referenced multiple times.

---

From: Jacob Champion <[email-masked]>
Date: Tue, 16 Dec 2025 15:09:51 -0800

Sorry for missing this thread!

> pg_hba.conf, while custom parameters must be set in postgresql.conf.

Yeah. (This has come up before a couple of times that I know of, in
the context of pg_hba and pg_ident splitting important configuration
between them [1], and in the context of SNI's proposed pg_hosts config
[2].)

> instance, but the question is certainly reasonable.

What kinds of parameters? Having a motivating use case would be
helpful; HBA isn't always as flexible as people assume and I want to
make sure that we can end with a usable feature.

> pg_hba.conf extensible.

Your proposals (and the concerns they raise) seem reasonable enough at
first glance. (I still want a motivating use case, though.)

Honestly, I'd *prefer* that any solution not be OAuth-specific. I
might throw two alternatives onto the pile:

d. Have HBA plug into the GUC system itself

A hypothetical PGC_HBA context would seem to fit nicely between
PGC_SIGHUP and PGC_SU_BACKEND.

e. Subsume HBA, ident, (hosts,) etc. under postgresql.conf

This is my personal white whale. I think pg_hba+ident is no longer fit
for purpose. It makes nonexistent use cases easy and common use cases
unnecessarily difficult. Most people ignore half the columns. New
users are surprised that you can't choose between authentication
options. You have to correlate a bunch of different files with
differing syntaxes to figure out what is going on. Etc, etc.

This is why I bypassed pg_ident for validators, so that they could be
free to do useful stuff while the core caught up. But I didn't intend
to keep them separate forever.

(I'm only halfway serious with (e) -- I don't really intend to drive
your thread straight into a wall. But when I read proposals a-c, I get
the sinking feeling that this *should* be solved in a more radical
way, if we could only agree on a direction...)

Thanks,
--Jacob

[1] https://postgr.es/m/0e0c038ab962c3f6dab00934fe5ae1ae115f44c0.camel%40vmware.com
[2] https://postgr.es/m/CAOYmi%2B%3DZjGJLw8tCkzY88acd%3Dir1r8eAxO-%2B5wXm9gtCUV97Sg%40mail.gmail.com

---

From: VASUKI M <[email-masked]>
Date: Wed, 17 Dec 2025 12:00:44 +0530

Hi All,

The core issue,as you said,is that OAuth validators can add custom
validation logic,but they can't define their own authentication-related
parameters in pg_hba.conf,where they naturally belong.Because of
that,validator-specific config ends up pushed into postgresql.conf via
GUCs,which feels a bit awkward and scattered.

That leads to the same points you mentioned:

1]OAuth configuration gets split between pg_hba.conf and
postgres.conf,which is confusing to reason about.
2]using multiple OIDC/OAuth providers with different parameter sets on a
single Postgresql instance is hard(or effectively impossible),even though
it's a pretty reasonable use case.

Given the constraints of the current HBA model(and similar issues that
recently came up with SNI),I agree that anything involving generic
extensibility or nested configuration would be a big hammer and likely too
complex.

> file and referenced multiple times.
So the direction I'm most aligned with is option (b): letting OAuth
validator advertise a limited list of additional valid option names for
pg_hba.conf,while keeping parsing,ordering rules,and validation firmly in
core.That seems like the least spicy option-incremental,OAuth-scoped,and
not a redesign of HBA parsing.

Reg. ordering:requiring validator= to appear before validator-specific
options feels acceptable to me if this is pursued,since it keeps parsing
simple and avoids ambiguity.
Reg very long HBA lines: totally agree this is a real readability issue,but
allowing per-line includes or external file feels like a seperate(and much
bigger)topic,probably best tackled independently.

Overall, +1 that this limitation is real and worth discussing.I’ll plan to
send a patch shortly exploring option (b).

Regards,

Vasuki M
CDAC,Chennai.

---

From: Zsolt Parragi <[email-masked]>
Date: Wed, 17 Dec 2025 09:33:51 +0000

> make sure that we can end with a usable feature.

One issue we have is that some providers don't allow users to select
what goes into the subject claim, but do allow users to define custom
claims. Additionally, the subject claim is sometimes a random
generated id, which gets generated on the first login to the client,
and that makes it practically unusable for pg. It would require:

* user trying to login to pg
* getting rejected
* figuring out what's the subject
* adding it to pg ident / some other config
* user can finally login

Instead we decided to let everyone configure which claim they want to
use for user mapping. But because of that, this is a GUC, and they can
only configure it once pre server.

The postgres-keycloak-oauth-validator is in an even worse situation,
they decided to use a long list of GUC parameters[1]. The main reason
is that they use an introspection endpoint for validation instead of
the JWT, so they need multiple parameters for that. Some of these GUCs
seem redundant to me, but some of them are definitely required.

They also have parameters for the client id and debugging - those are
things we are also considering adding to our validator.

> way, if we could only agree on a direction...)

I tried to propose simple things that are relatively easy to
implement, and wouldn't change too much at once, so there's a
realistic change for this making into PG19. I'm not against having a
bigger goal, and continuing making it even better after that.

> PGC_SIGHUP and PGC_SU_BACKEND.

How would you configure that since the hba lines don't have IDs?
Should we add a "guc_name" parameter to HBA for this or something like
that? I like this idea, it would be fun to implement and see how it
works, I'm just wondering how users could use it.

[1]: https://github.com/cloudnative-pg/postgres-keycloak-oauth-validator/blob/5fceacf53c3d86fbbe18dab0341311855a89fe6a/src/kc_validator.c#L741

---

From: Zsolt Parragi <[email-masked]>
Date: Wed, 17 Dec 2025 09:35:51 +0000

> Overall, +1 that this limitation is real and worth discussing.I’ll plan to send a patch shortly exploring option (b).

Personally I would go with either (a) or (c), and I was planning to
clean up / improve / share my (c) patch as a second attempt for this
thread, if it didn't receive any replies. I can still do that, so that
we have multiple test implementations. (b) seemed a not as nice design
to me, but maybe you find a better way to implement it than I did.

Also now I really like the idea of the PGC_HBA, if there's a way for
users to configure it without depending on line numbers or other
easy-to-change details.

---

From: Jacob Champion <[email-masked]>
Date: Wed, 17 Dec 2025 10:27:44 -0800

> Overall, +1 that this limitation is real and worth discussing.I’ll plan to send a patch shortly exploring option (b).

Thanks!

> Reg very long HBA lines: totally agree this is a real readability issue,but allowing per-line includes or external file feels like a seperate(and much bigger)topic,probably best tackled independently.

I forgot to mention in my reply to Zsolt, but we've supported inline
inclusions in HBA for a few releases now. (I just frequently forget
they exist.)

pg_hba.conf:

    hostssl  all  all  0.0.0.0/0  oauth  @oauth-settings.conf

oauth-settings.conf:

    issuer=https://oauth.example.org/v2
    scope="openid email let-me-into-pg"
    validator=example_org
    map=examplemap

And for smaller annoyances, you can wrap lines with backslash continuation.

I haven't used these new features much, since I forget they exist, so
if there are usability problems in practice please say something so we
can fix it.

--Jacob

---

From: Jacob Champion <[email-masked]>
Date: Wed, 17 Dec 2025 11:01:20 -0800

> only configure it once pre server.

We're getting closer; I agree that this needs to be more flexible than
it is, and I'm on board with a change, but I'm still missing the
"killer app". What's the case where a user has multiple HBA lines that
all want to use unrelated claims for authentication to one Postgres
cluster? Is this multi-tenancy, or...?

> bigger goal, and continuing making it even better after that.

Absolutely -- that's a tried and true strategy. No objections to that.

But I also didn't want to stay silent on my longer-term goals here.
That way (hopefully), no one's surprised to find I'm lukewarm on
patches that are extremely OAuth-specific, or that don't give us a way
to improve/evolve later. The additional flexibility of OAuth should
ideally be mirrored in other auth methods when possible.

> works, I'm just wondering how users could use it.

I hadn't thought it through very far; my initial impression was that
we'd need some sort of additional syntax. But I keep coming back to
httpd-style configs and then I choose something else from my TODO list
to focus on. :) See also the old conversation regarding LDAP hba/ident
[1].

On Wed, Dec 17, 2025 at 1:36 AM Zsolt Parragi <[email-masked]> wrote:
> we have multiple test implementations.

The more the merrier!

Thanks,
--Jacob

[1] https://postgr.es/m/CAOuzzgpFpuroNRabEvB9kST_TSyS2jFicBNoXvW7G2pZFixyBw%40mail.gmail.com

---

From: Zsolt Parragi <[email-masked]>
Date: Wed, 17 Dec 2025 23:52:57 +0000

> inclusions in HBA for a few releases now. (I just frequently forget

Thanks, I didn't know about that feature, that solves half of my problem.

> What's the case where a user has multiple HBA lines that

For configuring the authn matching yes, the use case is multitenancy.

But for some other variables that we didn't implement yet, this could
be useful even without multitenancy.

One thing I mentioned in the previous email is the client id
validation. A practical use case of that would be restricting which
oauth clients can login to which database. I can't use a SUSET
variable with a check restricting it to ALTER DATABASE, because
database level variables are not yet available during the oauth
validator callback. I could use a login event trigger, but that seems
like a bad hack to me.

---

From: VASUKI M <[email-masked]>
Date: Thu, 18 Dec 2025 10:44:05 +0530

On Thu, Dec 18, 2025 at 12:31 AM Jacob Champion <
[email-masked]> wrote:

> Beyond multitenancy,per -HBA OAuth  cases where options are needed for
safe provider migration[blue/green],per-database security policies,mixed
Human/machine authentication[JWT/Introspection] and incident-response
scenarios -all global GUCs are too coarse.

See also the old conversation regarding LDAP hba/ident
> [1]
>
> [1]
> https://postgr.es/m/CAOuzzgpFpuroNRabEvB9kST_TSyS2jFicBNoXvW7G2pZFixyBw%40mail.gmail.com

 Thanks, Will go through it.

Regards,

Vasuki M
CDAC,Chennai.

---

From: Zsolt Parragi <[email-masked]>
Date: Thu, 18 Dec 2025 09:08:10 +0000

> we have multiple test implementations.

I attached the patch. It modifies one of the existing oauth_validator
tests to showcase how it works, but in theory it isn't dependent on
oauth. It however requires shared_preload_libraries (that is common
for all options), maybe oauth_validator_libraries could imply that?

---

From: Jacob Champion <[email-masked]>
Date: Thu, 18 Dec 2025 09:27:22 -0800

On Thu, Dec 18, 2025 at 1:08 AM Zsolt Parragi <[email-masked]> wrote:
>
> It however requires shared_preload_libraries (that is common

Haven't looked at the patch yet, but I think most people probably want
to use session_preload_libraries, not shared_preload_libraries, so
that a security update to their validator doesn't require a restart of
the cluster.

If a particular validator implementation requires shared preload, so
be it; but I don't think we want to force it. Might be more reason to
look into the GUC system?

--Jacob

---

From: Zsolt Parragi <[email-masked]>
Date: Thu, 18 Dec 2025 18:28:11 +0000

> Might be more reason to look into the GUC system?

I am already thinking about that, I have some ideas for a proof of
concept, but no working prototype yet. But without requiring
shared_preload_libraries, we can't do early error reporting during
postmaster startup about custom parameters. Is that okay? GUCs already
work this way, and this could be a bit safer (reporting unknown
parameters/refusing to proceed during login, when we can completely
parse all parameters), but it would be different compared to how
pg_hba is handled currently.

---

From: Jacob Champion <[email-masked]>
Date: Thu, 18 Dec 2025 10:43:01 -0800

On Thu, Dec 18, 2025 at 10:28 AM Zsolt Parragi
<[email-masked]> wrote:
> But without requiring
> postmaster startup about custom parameters. Is that okay?

I think I need to do more staring at the intersection of GUC
registration and session_preload_libraries, because my memory of the
order of operations was faulty. I won't be able to do that before the
holidays, most likely.

--Jacob

---

From: Zsolt Parragi <[email-masked]>
Date: Thu, 18 Dec 2025 20:29:20 +0000

> order of operations was faulty. I won't be able to do that before the

Maybe I'm missing something, but why do we need
session_preload_libraries? oauth_validator_libraries is processed
earlier, it can already define sighup GUCs, it should also work with a
new level around that. I assume that if postgres gets another
authentication plugin point later, it will be executed around the same
place, during authentication, so that also shouldn't be an issue.

The question is if non-validator libraries should be able to define
PGC_HBA variables. If yes, then either

* we don't validate that all HBA variables are valid - if somebody
made a typo, we can't detect it
* we add a sighup guc with a manual whitelist
* require shared preload libraries or oauth_validator_libraries,
because those are loaded before or during authentication
* require session_preload_libraries. We proceed with authentication
even with unresolved HBA variables, but abort the connection if there
are still unknown parameters after loading session preload.