Thread: dispchar for oauth_client_secret

dispchar for oauth_client_secret

From
Noah Misch
Date:
commit b3f0be7 wrote:
+    {"oauth_scope", NULL, NULL, NULL,
+        "OAuth-Scope", "", 15,
+    offsetof(struct pg_conn, oauth_scope)},

The field containing "" is documented as follows:

    char       *dispchar;        /* Indicates how to display this field in a
                                 * connect dialog. Values are: "" Display
                                 * entered value as is "*" Password field -
                                 * hide value "D"  Debug option - don't show
                                 * by default */

I suspect this should use .dispchar="*" to encourage UIs to display
oauth_client_secret like a password field.  Thoughts?

[I didn't review commit b3f0be7, but this caught my attention.]



Re: dispchar for oauth_client_secret

From
Jacob Champion
Date:
On Tue, Apr 15, 2025 at 12:14 PM Noah Misch <noah@leadboat.com> wrote:
> I suspect this should use .dispchar="*" to encourage UIs to display
> oauth_client_secret like a password field.  Thoughts?

Hmm, from a UI perspective I agree. (The builtin flow targets "public
clients", where secrets are discouraged and/or understood to be
not-really-secret, but there's no reason to assume that all flows used
by the application are public.)

From a proxy perspective, this would mess with FDW handling. By making
the dispchar '*', oauth_client_secret will be made into a user mapping
option rather than a server option. (Neither is very useful to
postgres_fdw anyway, because the builtin flow needs an end user to
interact with the provider.) But I'm not sure if we'll need to handle
compatibility in the future if we implement a proxy-friendly flow. Is
it okay to move options back and forth during a major version bump? I
assume it would present a problem for pg_upgrade?

Thanks!
--Jacob



Re: dispchar for oauth_client_secret

From
Noah Misch
Date:
On Tue, Apr 15, 2025 at 01:16:12PM -0700, Jacob Champion wrote:
> On Tue, Apr 15, 2025 at 12:14 PM Noah Misch <noah@leadboat.com> wrote:
> > I suspect this should use .dispchar="*" to encourage UIs to display
> > oauth_client_secret like a password field.  Thoughts?
> 
> Hmm, from a UI perspective I agree. (The builtin flow targets "public
> clients", where secrets are discouraged and/or understood to be
> not-really-secret, but there's no reason to assume that all flows used
> by the application are public.)
> 
> From a proxy perspective, this would mess with FDW handling. By making
> the dispchar '*', oauth_client_secret will be made into a user mapping
> option rather than a server option. (Neither is very useful to
> postgres_fdw anyway, because the builtin flow needs an end user to
> interact with the provider.) But I'm not sure if we'll need to handle
> compatibility in the future if we implement a proxy-friendly flow.

If we think oauth_client_secret should get dispchar="*" UI treatment yet be a
postgres_fdw server option, postgres_fdw code can make it so.  postgres_fdw
already has explicit code to reclassify the "user" option.

> Is
> it okay to move options back and forth during a major version bump?  I
> assume it would present a problem for pg_upgrade?

It would break dump/reload, so it's best not to move options between
optcontext=ForeignServerRelationId and optcontext=UserMappingRelationId, even
at major versions.  As above, we can change dispchar separately from
optcontext.  The documentation of dispchar likely should tell people to update
the postgres_fdw documentation when adding a dispchar="*' option.

It sounds like we might end up wanting to allow oauth_client_secret in both of
ForeignServerRelationId and UserMappingRelationId, each catering to different
oauth implementations.  Is that right?  (It would be fine to allow one today
and later change to allow both.)



Re: dispchar for oauth_client_secret

From
Jacob Champion
Date:
On Tue, Apr 15, 2025 at 1:48 PM Noah Misch <noah@leadboat.com> wrote:
> If we think oauth_client_secret should get dispchar="*" UI treatment yet be a
> postgres_fdw server option, postgres_fdw code can make it so.  postgres_fdw
> already has explicit code to reclassify the "user" option.

Agreed, I will add an open item.

> The documentation of dispchar likely should tell people to update
> the postgres_fdw documentation when adding a dispchar="*' option.

(Or dispchar="D".)

> It sounds like we might end up wanting to allow oauth_client_secret in both of
> ForeignServerRelationId and UserMappingRelationId, each catering to different
> oauth implementations.  Is that right?  (It would be fine to allow one today
> and later change to allow both.)

I think, for the short-to-medium term, it is best to think of
oauth_client_id/oauth_client_secret/oauth_issuer as a packaged triple.
You don't want to use a secret with the wrong client ID, you don't
want to send a secret to the wrong provider, and one provider's client
ID won't be recognized by another. There might be some providers that
let you issue multiple secrets per client ID, but I seem to recall
that's intended more for rotation than it is for separate end users.

(It is true that separate users could make use of separate issuers
entirely. But that's conceptually separate from allowing a user to
control the HTTP entry point of server-side libpq without OWNER
privilege on the server. I don't like that at all from a risk
management perspective, and I'd prefer that we keep oauth_issuer on
the server context. It might be safe at some point to pull both
oauth_client_id and _secret down to the user context, once there's a
use case.)

Thanks!
--Jacob



Re: dispchar for oauth_client_secret

From
Jelte Fennema-Nio
Date:
On Tue, 15 Apr 2025 at 22:48, Noah Misch <noah@leadboat.com> wrote:
> yet be a
> postgres_fdw server option, postgres_fdw code can make it so.  postgres_fdw
> already has explicit code to reclassify the "user" option.

I don't understand why it should be a server option instead of a user
mapping option. Having it be a server option means that *any* Postgres
user can read its contents. My knowledge on the purpose is pretty
limited, but having that be the case for something with "secret" in
the name seems very unintuitive.



Re: dispchar for oauth_client_secret

From
Jacob Champion
Date:
On Tue, Apr 15, 2025 at 3:25 PM Jelte Fennema-Nio <postgres@jeltef.nl> wrote:
> I don't understand why it should be a server option instead of a user
> mapping option. Having it be a server option means that *any* Postgres
> user can read its contents.

Thank you for saying something; I'd hallucinated that srvoptions was
limited to the server owner, and that's not true. It's pg_user_mapping
that has the protection.

But if you want to hide the client secret from your users, making it a
user mapping option has not made the situation better. The client ID
and secret are there to authenticate libpq (and by extension,
postgres_fdw), not the end user.

> My knowledge on the purpose is pretty
> limited, but having that be the case for something with "secret" in
> the name seems very unintuitive.

From the point of view of a proxy, whether you use a secret at all is
up to the flow in use. And for 18, the only supported flow is focused
on authorizing an actual human at the keyboard, without any token
caching, making it pretty unhelpful for FDW. A more proxy-friendly
flow would be awesome -- and/or explicit integration of the existing
builtin flow into the proxies, both safely and helpfully -- but that's
not a v18 thing. (I view it as similar in spirit to the
SCRAM-passthrough work.)

So: maybe it'd be best to disallow the OAuth options in the proxy code
entirely, so that a proxy-friendly future implementation is not
accidentally tied to decisions we made in v18.

--Jacob



Re: dispchar for oauth_client_secret

From
Jelte Fennema-Nio
Date:
On Wed, 16 Apr 2025 at 02:03, Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
> Thank you for saying something; I'd hallucinated that srvoptions was
> limited to the server owner, and that's not true. It's pg_user_mapping
> that has the protection.

FWIW, I have some ideas on being able to store secrets in a server in
a safe way. I'll probably start a thread on that somewhere in the next
few months.

> So: maybe it'd be best to disallow the OAuth options in the proxy code
> entirely, so that a proxy-friendly future implementation is not
> accidentally tied to decisions we made in v18.

Seems fine to me.

On Wed, 16 Apr 2025 at 02:03, Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
>
> On Tue, Apr 15, 2025 at 3:25 PM Jelte Fennema-Nio <postgres@jeltef.nl> wrote:
> > I don't understand why it should be a server option instead of a user
> > mapping option. Having it be a server option means that *any* Postgres
> > user can read its contents.
>
> Thank you for saying something; I'd hallucinated that srvoptions was
> limited to the server owner, and that's not true. It's pg_user_mapping
> that has the protection.
>
> But if you want to hide the client secret from your users, making it a
> user mapping option has not made the situation better. The client ID
> and secret are there to authenticate libpq (and by extension,
> postgres_fdw), not the end user.
>
> > My knowledge on the purpose is pretty
> > limited, but having that be the case for something with "secret" in
> > the name seems very unintuitive.
>
> From the point of view of a proxy, whether you use a secret at all is
> up to the flow in use. And for 18, the only supported flow is focused
> on authorizing an actual human at the keyboard, without any token
> caching, making it pretty unhelpful for FDW. A more proxy-friendly
> flow would be awesome -- and/or explicit integration of the existing
> builtin flow into the proxies, both safely and helpfully -- but that's
> not a v18 thing. (I view it as similar in spirit to the
> SCRAM-passthrough work.)
>
> So: maybe it'd be best to disallow the OAuth options in the proxy code
> entirely, so that a proxy-friendly future implementation is not
> accidentally tied to decisions we made in v18.
>
> --Jacob