public inbox for [email protected]
help / color / mirror / Atom feedFrom: Jacob Champion <[email protected]>
To: Zsolt Parragi <[email protected]>
Cc: PostgreSQL Hackers <[email protected]>
Subject: Re: [oauth] Split and extend PGOAUTHDEBUG
Date: Mon, 30 Mar 2026 14:41:38 -0700
Message-ID: <CAOYmi+k_et3yXpJ8op71-95j7OYg-kX5bWLgW9YTV_5G7f+O1A@mail.gmail.com> (raw)
In-Reply-To: <CAN4CZFMmDZMH56O9vb_g7vHqAk8ryWFxBMV19C39PFghENg8kA@mail.gmail.com>
References: <CAN4CZFMmDZMH56O9vb_g7vHqAk8ryWFxBMV19C39PFghENg8kA@mail.gmail.com>
On Wed, Feb 18, 2026 at 7:08 AM Zsolt Parragi <[email protected]> wrote:
> 1 is the same patch I already sent as part of the PGOAUTHCAFILE
> discussion[1], rebased on the current master: it splits
> PGOAUTHDEBUG=UNSAFE into separate unsafe/safe settings which users can
> toggle one by one.
>
> 2 is a new unsafe setting issuer-mismatch, which allows a connection
> to continue if the client and server issuers don't match. While this
> isn't useful for end users, it makes testing validators easier, as
> validators authors should be able to verify that mismatched
> configurations are rejected properly by the validator.
v2, attached, rebases this over 993368113. The big change is the
removal of `custom-ca`; there were a couple of other tweaks to get
both commits compiling independently.
--Jacob
Attachments:
[application/octet-stream] since-v1.nocfbot.diff (14.2K, 2-since-v1.nocfbot.diff)
download | inline diff:
1: 5853d79e0d4 ! 1: e51f717e07c Split PGOAUTHDEBUG=UNSAFE into multiple options
@@ Commit message
Split PGOAUTHDEBUG=UNSAFE into multiple options
## doc/src/sgml/libpq.sgml ##
-@@ doc/src/sgml/libpq.sgml: typedef struct PGoauthBearerRequest
- <title>Debugging and Developer Settings</title>
+@@ doc/src/sgml/libpq.sgml: typedef struct
+ </para>
<para>
- A "dangerous debugging mode" may be enabled by setting the environment
@@ doc/src/sgml/libpq.sgml: typedef struct PGoauthBearerRequest
- </listitem>
- <listitem>
- <para>
-- allows the system's trusted CA list to be completely replaced using the
-- <envar>PGOAUTHCAFILE</envar> environment variable
-- </para>
-- </listitem>
-- <listitem>
-- <para>
- prints HTTP traffic (containing several critical secrets) to standard
- error during the OAuth flow
- </para>
@@ doc/src/sgml/libpq.sgml: typedef struct PGoauthBearerRequest
+ </varlistentry>
+
+ <varlistentry>
-+ <term><literal>custom-ca</literal> (unsafe)</term>
-+ <listitem>
-+ <para>
-+ Allows the system's trusted CA list to be completely replaced using the
-+ <envar>PGOAUTHCAFILE</envar> environment variable. This can facilitate
-+ man-in-the-middle attacks when testing with self-signed certificates.
-+ </para>
-+ </listitem>
-+ </varlistentry>
-+
-+ <varlistentry>
+ <term><literal>fast-retry</literal> (safe)</term>
+ <listitem>
+ <para>
@@ doc/src/sgml/libpq.sgml: typedef struct PGoauthBearerRequest
+ </para>
+
+ <para>
-+ Unsafe options (<literal>http</literal>, <literal>trace</literal>,
-+ <literal>custom-ca</literal>) require the <literal>UNSAFE:</literal> prefix.
++ Unsafe options (<literal>http</literal>, <literal>trace</literal>)
++ require the <literal>UNSAFE:</literal> prefix.
+ If unsafe options are specified without this prefix, a warning is printed
+ to standard error and that option is ignored. Other valid options in the
+ list continue to work. Safe options (<literal>fast-retry</literal>,
+ <literal>poll-counts</literal>, <literal>print-plugin-errors</literal>) can
+ be used without the prefix.
-+ </para>
+ </para>
+
+ <para>
+ Unrecognized option names will also trigger a warning and be ignored, while
+ valid options continue to work. This helps catch typos in the environment
+ variable configuration without breaking the debugging of valid options.
- </para>
++ </para>
+
+ <para>
+ Examples:
+ <programlisting>
+PGOAUTHDEBUG=fast-retry,poll-counts <lineannotation>safe options only</lineannotation>
+PGOAUTHDEBUG=UNSAFE:http,trace <lineannotation>enable HTTP and traffic logging</lineannotation>
-+PGOAUTHDEBUG=UNSAFE:http,custom-ca,poll-counts <lineannotation>mix of unsafe and safe</lineannotation>
++PGOAUTHDEBUG=UNSAFE:http,poll-counts <lineannotation>mix of unsafe and safe</lineannotation>
+PGOAUTHDEBUG=UNSAFE <lineannotation>legacy; enables all options</lineannotation>
+ </programlisting>
+ </para>
@@ src/interfaces/libpq/meson.build
'fe-cancel.c',
## src/interfaces/libpq-oauth/Makefile ##
-@@ src/interfaces/libpq-oauth/Makefile: override CFLAGS += $(PTHREAD_CFLAGS)
+@@ src/interfaces/libpq-oauth/Makefile: override CPPFLAGS_SHLIB += -DUSE_PRIVATE_ENCODING_FUNCS
OBJS = \
$(WIN32RES)
@@ src/interfaces/libpq-oauth/Makefile: override CFLAGS += $(PTHREAD_CFLAGS)
oauth-utils.o \
+ fe-auth-oauth-debug_shlib.o
- oauth-utils.o: override CPPFLAGS += -DUSE_DYNAMIC_OAUTH
- oauth-curl_shlib.o: override CPPFLAGS_SHLIB += -DUSE_DYNAMIC_OAUTH
-+fe-auth-oauth-debug_shlib.o: override CPPFLAGS_SHLIB += -DUSE_DYNAMIC_OAUTH
-+
+ oauth-utils.o: override CPPFLAGS += $(CPPFLAGS_SHLIB)
+
+fe-auth-oauth-debug.o: $(libpq_srcdir)/fe-auth-oauth-debug.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+
-+fe-auth-oauth-debug_shlib.o: $(libpq_srcdir)/fe-auth-oauth-debug.c
++fe-auth-oauth-debug_shlib.o: $(libpq_srcdir)/fe-auth-oauth-debug.c fe-auth-oauth-debug.o
+ $(CC) $(CFLAGS) $(CFLAGS_SL) $(CPPFLAGS) $(CPPFLAGS_SHLIB) -c $< -o $@
-
++
# Add shlib-/stlib-specific objects.
$(shlib): override OBJS += $(OBJS_SHLIB)
+ $(shlib): $(OBJS_SHLIB)
## src/interfaces/libpq/Makefile ##
@@ src/interfaces/libpq/Makefile: OBJS = \
@@ src/interfaces/libpq/Makefile: OBJS = \
ifneq ($(with_ssl),no)
## src/interfaces/libpq-oauth/oauth-utils.h ##
+@@
+ #ifndef OAUTH_UTILS_H
+ #define OAUTH_UTILS_H
+
++#include "fe-auth-oauth.h"
+ #include "libpq-fe.h"
+ #include "pqexpbuffer.h"
+
@@ src/interfaces/libpq-oauth/oauth-utils.h: typedef enum
+ PG_BOOL_NO /* No (false) */
} PGTernaryBool;
- extern void libpq_append_conn_error(PGconn *conn, const char *fmt,...) pg_attribute_printf(2, 3);
-extern bool oauth_unsafe_debugging_enabled(void);
+extern oauth_debug_flags oauth_get_debug_flags(void);
extern int pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending);
@@ src/interfaces/libpq/fe-auth-oauth.h: typedef struct
+ /* UNSAFE features - require UNSAFE: prefix */
+ bool http; /* allow HTTP (unencrypted) connections */
+ bool trace; /* log HTTP traffic (exposes secrets) */
-+ bool custom_ca; /* allow custom CA certificate file */
+
+ /* SAFE features - allowed without UNSAFE: prefix */
+ bool fast_retry; /* allow zero-second retry intervals */
@@ src/interfaces/libpq/fe-auth-oauth.h: typedef struct
extern void pqClearOAuthToken(PGconn *conn);
-extern bool oauth_unsafe_debugging_enabled(void);
+extern oauth_debug_flags oauth_get_debug_flags(void);
- extern bool use_builtin_flow(PGconn *conn, fe_oauth_state *state);
/* Mechanisms in fe-auth-oauth.c */
+ extern const pg_fe_sasl_mech pg_oauth_mech;
## src/interfaces/libpq-oauth/oauth-curl.c ##
@@ src/interfaces/libpq-oauth/oauth-curl.c: struct async_ctx
@@ src/interfaces/libpq-oauth/oauth-curl.c: setup_curl_handles(struct async_ctx *ac
protos = unsafe;
CHECK_SETOPT(actx, popt, protos, return false);
-@@ src/interfaces/libpq-oauth/oauth-curl.c: setup_curl_handles(struct async_ctx *actx)
- * the flow to work at all, so any changes to the roots are likely to be
- * done system-wide.
- */
-- if (actx->debugging)
-+ if (actx->debug_flags.custom_ca)
- {
- const char *env;
-
@@ src/interfaces/libpq-oauth/oauth-curl.c: check_for_device_flow(struct async_ctx *actx)
* decent time to bail out if we're not using HTTPS for the endpoints
* we'll use for the flow.
@@ src/interfaces/libpq-oauth/oauth-curl.c: check_for_device_flow(struct async_ctx
{
if (pg_strncasecmp(provider->device_authorization_endpoint,
HTTPS_SCHEME, strlen(HTTPS_SCHEME)) != 0)
-@@ src/interfaces/libpq-oauth/oauth-curl.c: pg_fe_run_oauth_flow_impl(PGconn *conn)
- actx->mux = PGINVALID_SOCKET;
- actx->timerfd = -1;
-
-- /* Should we enable unsafe features? */
-- actx->debugging = oauth_unsafe_debugging_enabled();
-+ /* Parse debug flags from environment */
-+ actx->debug_flags = oauth_get_debug_flags();
-
- state->async_ctx = actx;
-
-@@ src/interfaces/libpq-oauth/oauth-curl.c: pg_fe_run_oauth_flow(PGconn *conn)
- actx = state->async_ctx;
- Assert(actx || result == PGRES_POLLING_FAILED);
-
-- if (actx && actx->debugging)
+@@ src/interfaces/libpq-oauth/oauth-curl.c: pg_fe_run_oauth_flow(PGconn *conn, struct PGoauthBearerRequest *request,
+ * drain_timer_events(), when we're in debug mode, track the total number
+ * of calls to this function and print that at the end of the flow.
+ */
+- if (actx->debugging)
+ if (actx && actx->debug_flags.poll_counts)
{
actx->dbg_num_calls++;
if (result == PGRES_POLLING_OK || result == PGRES_POLLING_FAILED)
+@@ src/interfaces/libpq-oauth/oauth-curl.c: pg_start_oauthbearer(PGconn *conn, PGoauthBearerRequestV2 *request)
+ * Now finish filling in the actx.
+ */
+
+- /* Should we enable unsafe features? */
+- actx->debugging = oauth_unsafe_debugging_enabled();
++ /* Parse debug flags from the environment. */
++ actx->debug_flags = oauth_get_debug_flags();
+
+ initPQExpBuffer(&actx->work_data);
+ initPQExpBuffer(&actx->errbuf);
## src/interfaces/libpq-oauth/oauth-utils.c ##
@@ src/interfaces/libpq-oauth/oauth-utils.c: libpq_gettext(const char *msgid)
@@ src/interfaces/libpq-oauth/test-oauth-curl.c: init_test_actx(void)
- actx->debugging = true;
+ actx->debug_flags.http = true;
+ actx->debug_flags.trace = true;
-+ actx->debug_flags.custom_ca = true;
-+ actx->debug_flags.issuer_mismatch = true;
+ actx->debug_flags.fast_retry = true;
+ actx->debug_flags.poll_counts = true;
+ actx->debug_flags.print_plugin_errors = true;
@@ src/interfaces/libpq/fe-auth-oauth-debug.c (new)
+ *is_unsafe = true;
+ return true;
+ }
-+ else if (strcmp(option, "custom-ca") == 0)
-+ {
-+ flags->custom_ca = true;
-+ *is_unsafe = true;
-+ return true;
-+ }
+ /* Safe options */
+ else if (strcmp(option, "fast-retry") == 0)
+ {
@@ src/interfaces/libpq/fe-auth-oauth-debug.c (new)
+ {
+ flags.http = true;
+ flags.trace = true;
-+ flags.custom_ca = true;
+ flags.fast_retry = true;
+ flags.poll_counts = true;
+ flags.print_plugin_errors = true;
@@ src/interfaces/libpq/fe-auth-oauth.c: issuer_from_well_known_uri(PGconn *conn, c
&& pg_strncasecmp(wkuri, HTTP_SCHEME, strlen(HTTP_SCHEME)) == 0)
{
/* Allow http:// for testing only. */
-@@ src/interfaces/libpq/fe-auth-oauth.c: use_builtin_flow(PGconn *conn, fe_oauth_state *state)
+@@ src/interfaces/libpq/fe-auth-oauth.c: use_builtin_flow(PGconn *conn, fe_oauth_state *state, PGoauthBearerRequestV2 *re
*
* Note that POSIX dlerror() isn't guaranteed to be threadsafe.
*/
@@ src/interfaces/libpq/fe-auth-oauth.c: use_builtin_flow(PGconn *conn, fe_oauth_st
+ if (oauth_get_debug_flags().print_plugin_errors)
fprintf(stderr, "failed dlopen for libpq-oauth: %s\n", dlerror());
- return false;
-@@ src/interfaces/libpq/fe-auth-oauth.c: use_builtin_flow(PGconn *conn, fe_oauth_state *state)
- * This is more of an error condition than the one above, but due to
- * the dlerror() threadsafety issue, lock it behind PGOAUTHDEBUG too.
+ return 0;
+@@ src/interfaces/libpq/fe-auth-oauth.c: use_builtin_flow(PGconn *conn, fe_oauth_state *state, PGoauthBearerRequestV2 *re
+ * cause is still locked behind PGOAUTHDEBUG due to the dlerror()
+ * threadsafety issue.
*/
- if (oauth_unsafe_debugging_enabled())
+ if (oauth_get_debug_flags().print_plugin_errors)
2: 5fc7a19876b ! 2: 933f6432f87 Add new PGOAUTHDEBUG option: issuer-mismatch
@@ doc/src/sgml/libpq.sgml: PGOAUTHDEBUG=UNSAFE <lineannotation>legacy format; e
<term><literal>fast-retry</literal> (safe)</term>
<listitem>
@@ doc/src/sgml/libpq.sgml: PGOAUTHDEBUG=UNSAFE <lineannotation>legacy format; enables all options</linea
+ </para>
<para>
- Unsafe options (<literal>http</literal>, <literal>trace</literal>,
-- <literal>custom-ca</literal>) require the <literal>UNSAFE:</literal> prefix.
-+ <literal>custom-ca</literal>, <literal>issuer-mismatch</literal>) require the <literal>UNSAFE:</literal> prefix.
+- Unsafe options (<literal>http</literal>, <literal>trace</literal>)
+- require the <literal>UNSAFE:</literal> prefix.
++ Unsafe options (<literal>http</literal>, <literal>trace</literal>,
++ <literal>issuer-mismatch</literal>) require the <literal>UNSAFE:</literal> prefix.
If unsafe options are specified without this prefix, a warning is printed
to standard error and that option is ignored. Other valid options in the
list continue to work. Safe options (<literal>fast-retry</literal>,
## src/interfaces/libpq/fe-auth-oauth.h ##
@@ src/interfaces/libpq/fe-auth-oauth.h: typedef struct oauth_debug_flags
+ /* UNSAFE features - require UNSAFE: prefix */
bool http; /* allow HTTP (unencrypted) connections */
bool trace; /* log HTTP traffic (exposes secrets) */
- bool custom_ca; /* allow custom CA certificate file */
+ bool issuer_mismatch; /* tolerate issuer mismatch */
/* SAFE features - allowed without UNSAFE: prefix */
@@ src/interfaces/libpq-oauth/oauth-curl.c: check_issuer(struct async_ctx *actx, PG
return true;
+ ## src/interfaces/libpq-oauth/test-oauth-curl.c ##
+@@ src/interfaces/libpq-oauth/test-oauth-curl.c: init_test_actx(void)
+ actx->timerfd = -1;
+ actx->debug_flags.http = true;
+ actx->debug_flags.trace = true;
++ actx->debug_flags.issuer_mismatch = true;
+ actx->debug_flags.fast_retry = true;
+ actx->debug_flags.poll_counts = true;
+ actx->debug_flags.print_plugin_errors = true;
+
## src/interfaces/libpq/fe-auth-oauth-debug.c ##
@@ src/interfaces/libpq/fe-auth-oauth-debug.c: parse_debug_option(const char *option, oauth_debug_flags *flags, bool *is_unsafe
*is_unsafe = true;
@@ src/interfaces/libpq/fe-auth-oauth-debug.c: parse_debug_option(const char *optio
else if (strcmp(option, "fast-retry") == 0)
{
@@ src/interfaces/libpq/fe-auth-oauth-debug.c: oauth_get_debug_flags(void)
+ {
flags.http = true;
flags.trace = true;
- flags.custom_ca = true;
+ flags.issuer_mismatch = true;
flags.fast_retry = true;
flags.poll_counts = true;
[application/octet-stream] v2-0001-Split-PGOAUTHDEBUG-UNSAFE-into-multiple-options.patch (19.4K, 3-v2-0001-Split-PGOAUTHDEBUG-UNSAFE-into-multiple-options.patch)
download | inline diff:
From e51f717e07c6374c99c198a3ac18b6df67fb1620 Mon Sep 17 00:00:00 2001
From: Zsolt Parragi <[email protected]>
Date: Thu, 11 Dec 2025 23:56:08 +0000
Subject: [PATCH v2 1/2] Split PGOAUTHDEBUG=UNSAFE into multiple options
---
doc/src/sgml/libpq.sgml | 127 +++++++++++++----
src/interfaces/libpq-oauth/meson.build | 6 +-
src/interfaces/libpq/meson.build | 1 +
src/interfaces/libpq-oauth/Makefile | 11 +-
src/interfaces/libpq/Makefile | 3 +-
src/interfaces/libpq-oauth/oauth-utils.h | 3 +-
src/interfaces/libpq/fe-auth-oauth.h | 18 ++-
src/interfaces/libpq-oauth/oauth-curl.c | 16 +--
src/interfaces/libpq-oauth/oauth-utils.c | 11 --
src/interfaces/libpq-oauth/test-oauth-curl.c | 6 +-
src/interfaces/libpq/fe-auth-oauth-debug.c | 140 +++++++++++++++++++
src/interfaces/libpq/fe-auth-oauth.c | 16 +--
12 files changed, 295 insertions(+), 63 deletions(-)
create mode 100644 src/interfaces/libpq/fe-auth-oauth-debug.c
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index a48d3161495..2e5fb9011e9 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -10643,35 +10643,112 @@ typedef struct
</para>
<para>
- A "dangerous debugging mode" may be enabled by setting the environment
- variable <envar>PGOAUTHDEBUG=UNSAFE</envar>. This functionality is provided
- for ease of local development and testing only. It does several things that
- you will not want a production system to do:
+ Debug features may be enabled by setting the <envar>PGOAUTHDEBUG</envar>
+ environment variable. This functionality is provided for ease of local
+ development and testing. The variable accepts a comma-separated list of
+ debug options:
+
+ <programlisting>
+PGOAUTHDEBUG=option1,option2,... <lineannotation>for safe options only</lineannotation>
+PGOAUTHDEBUG=UNSAFE:option1,option2,... <lineannotation>when using unsafe options</lineannotation>
+PGOAUTHDEBUG=UNSAFE <lineannotation>legacy format; enables all options</lineannotation>
+ </programlisting>
+ </para>
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- permits the use of unencrypted HTTP during the OAuth provider exchange
- </para>
- </listitem>
- <listitem>
- <para>
- prints HTTP traffic (containing several critical secrets) to standard
- error during the OAuth flow
- </para>
- </listitem>
- <listitem>
- <para>
- permits the use of zero-second retry intervals, which can cause the
- client to busy-loop and pointlessly consume CPU
- </para>
- </listitem>
- </itemizedlist>
+ <para>
+ Available debug options:
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>http</literal> (unsafe)</term>
+ <listitem>
+ <para>
+ Permits the use of unencrypted HTTP during the OAuth provider exchange.
+ This allows OAuth credentials to be transmitted over unencrypted
+ connections, which is extremely dangerous and should only be used for
+ local testing.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>trace</literal> (unsafe)</term>
+ <listitem>
+ <para>
+ Prints HTTP traffic to standard error during the OAuth flow. This output
+ contains critical secrets including bearer tokens, client secrets, access
+ tokens, and authorization codes. Never share this output with third
+ parties.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>fast-retry</literal> (safe)</term>
+ <listitem>
+ <para>
+ Permits the use of zero-second retry intervals instead of the normal
+ minimum of one second. This can speed up tests but may cause the client
+ to busy-loop and consume CPU unnecessarily.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>poll-counts</literal> (safe)</term>
+ <listitem>
+ <para>
+ Prints the total number of poll() calls to standard error when the
+ OAuth flow completes. This helps developers debug the async multiplexer
+ behavior.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>print-plugin-errors</literal> (safe)</term>
+ <listitem>
+ <para>
+ Prints plugin loading errors to standard error. This helps developers
+ and package maintainers debug issues when the OAuth plugin fails to load.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para>
+ Unsafe options (<literal>http</literal>, <literal>trace</literal>)
+ require the <literal>UNSAFE:</literal> prefix.
+ If unsafe options are specified without this prefix, a warning is printed
+ to standard error and that option is ignored. Other valid options in the
+ list continue to work. Safe options (<literal>fast-retry</literal>,
+ <literal>poll-counts</literal>, <literal>print-plugin-errors</literal>) can
+ be used without the prefix.
</para>
+
+ <para>
+ Unrecognized option names will also trigger a warning and be ignored, while
+ valid options continue to work. This helps catch typos in the environment
+ variable configuration without breaking the debugging of valid options.
+ </para>
+
+ <para>
+ Examples:
+ <programlisting>
+PGOAUTHDEBUG=fast-retry,poll-counts <lineannotation>safe options only</lineannotation>
+PGOAUTHDEBUG=UNSAFE:http,trace <lineannotation>enable HTTP and traffic logging</lineannotation>
+PGOAUTHDEBUG=UNSAFE:http,poll-counts <lineannotation>mix of unsafe and safe</lineannotation>
+PGOAUTHDEBUG=UNSAFE <lineannotation>legacy; enables all options</lineannotation>
+ </programlisting>
+ </para>
+
<warning>
<para>
- Do not share the output of the OAuth flow traffic with third parties. It
- contains secrets that can be used to attack your clients and servers.
+ Never use unsafe debug options in production environments. The
+ <literal>trace</literal> option in particular exposes secrets that can be
+ used to attack your clients and servers. Do not share the output with third
+ parties.
</para>
</warning>
</sect2>
diff --git a/src/interfaces/libpq-oauth/meson.build b/src/interfaces/libpq-oauth/meson.build
index ea3a900f4f1..d8cc92e0c2c 100644
--- a/src/interfaces/libpq-oauth/meson.build
+++ b/src/interfaces/libpq-oauth/meson.build
@@ -6,6 +6,7 @@ endif
libpq_oauth_sources = files(
'oauth-curl.c',
+ '../libpq/fe-auth-oauth-debug.c',
)
# The shared library needs additional glue symbols.
@@ -62,7 +63,10 @@ endif
libpq_oauth_test_deps = []
-oauth_test_sources = files('test-oauth-curl.c') + libpq_oauth_so_sources
+oauth_test_sources = files(
+ 'test-oauth-curl.c',
+ '../libpq/fe-auth-oauth-debug.c',
+) + libpq_oauth_so_sources
if host_system == 'windows'
oauth_test_sources += rc_bin_gen.process(win32ver_rc, extra_args: [
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index b0ae72167a1..d031f4962e5 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -2,6 +2,7 @@
libpq_sources = files(
'fe-auth-oauth.c',
+ 'fe-auth-oauth-debug.c',
'fe-auth-scram.c',
'fe-auth.c',
'fe-cancel.c',
diff --git a/src/interfaces/libpq-oauth/Makefile b/src/interfaces/libpq-oauth/Makefile
index 11e1a3cf528..c6097dda531 100644
--- a/src/interfaces/libpq-oauth/Makefile
+++ b/src/interfaces/libpq-oauth/Makefile
@@ -36,15 +36,24 @@ override CPPFLAGS_SHLIB += -DUSE_PRIVATE_ENCODING_FUNCS
OBJS = \
$(WIN32RES)
-OBJS_STATIC = oauth-curl.o
+OBJS_STATIC = \
+ oauth-curl.o \
+ fe-auth-oauth-debug.o
# The shared library needs additional glue symbols.
OBJS_SHLIB = \
oauth-curl_shlib.o \
oauth-utils.o \
+ fe-auth-oauth-debug_shlib.o
oauth-utils.o: override CPPFLAGS += $(CPPFLAGS_SHLIB)
+fe-auth-oauth-debug.o: $(libpq_srcdir)/fe-auth-oauth-debug.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+
+fe-auth-oauth-debug_shlib.o: $(libpq_srcdir)/fe-auth-oauth-debug.c fe-auth-oauth-debug.o
+ $(CC) $(CFLAGS) $(CFLAGS_SL) $(CPPFLAGS) $(CPPFLAGS_SHLIB) -c $< -o $@
+
# Add shlib-/stlib-specific objects.
$(shlib): override OBJS += $(OBJS_SHLIB)
$(shlib): $(OBJS_SHLIB)
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 0963995eed4..099c6557e77 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -44,7 +44,8 @@ OBJS = \
legacy-pqsignal.o \
libpq-events.o \
pqexpbuffer.o \
- fe-auth.o
+ fe-auth.o \
+ fe-auth-oauth-debug.o
# File shared across all SSL implementations supported.
ifneq ($(with_ssl),no)
diff --git a/src/interfaces/libpq-oauth/oauth-utils.h b/src/interfaces/libpq-oauth/oauth-utils.h
index 293e9936989..dd4e38d525c 100644
--- a/src/interfaces/libpq-oauth/oauth-utils.h
+++ b/src/interfaces/libpq-oauth/oauth-utils.h
@@ -15,6 +15,7 @@
#ifndef OAUTH_UTILS_H
#define OAUTH_UTILS_H
+#include "fe-auth-oauth.h"
#include "libpq-fe.h"
#include "pqexpbuffer.h"
@@ -35,7 +36,7 @@ typedef enum
PG_BOOL_NO /* No (false) */
} PGTernaryBool;
-extern bool oauth_unsafe_debugging_enabled(void);
+extern oauth_debug_flags oauth_get_debug_flags(void);
extern int pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending);
extern void pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe);
diff --git a/src/interfaces/libpq/fe-auth-oauth.h b/src/interfaces/libpq/fe-auth-oauth.h
index 511284614f7..fde5c30c013 100644
--- a/src/interfaces/libpq/fe-auth-oauth.h
+++ b/src/interfaces/libpq/fe-auth-oauth.h
@@ -38,8 +38,24 @@ typedef struct
void *builtin_flow;
} fe_oauth_state;
+/*
+ * Debug flags for PGOAUTHDEBUG environment variable.
+ * Each flag controls a specific debug feature.
+ */
+typedef struct oauth_debug_flags
+{
+ /* UNSAFE features - require UNSAFE: prefix */
+ bool http; /* allow HTTP (unencrypted) connections */
+ bool trace; /* log HTTP traffic (exposes secrets) */
+
+ /* SAFE features - allowed without UNSAFE: prefix */
+ bool fast_retry; /* allow zero-second retry intervals */
+ bool poll_counts; /* print poll() statistics */
+ bool print_plugin_errors; /* print plugin loading errors */
+} oauth_debug_flags;
+
extern void pqClearOAuthToken(PGconn *conn);
-extern bool oauth_unsafe_debugging_enabled(void);
+extern oauth_debug_flags oauth_get_debug_flags(void);
/* Mechanisms in fe-auth-oauth.c */
extern const pg_fe_sasl_mech pg_oauth_mech;
diff --git a/src/interfaces/libpq-oauth/oauth-curl.c b/src/interfaces/libpq-oauth/oauth-curl.c
index 3baede1b2e7..564d76cf063 100644
--- a/src/interfaces/libpq-oauth/oauth-curl.c
+++ b/src/interfaces/libpq-oauth/oauth-curl.c
@@ -274,7 +274,7 @@ struct async_ctx
int running; /* is asynchronous work in progress? */
bool user_prompted; /* have we already sent the authz prompt? */
bool used_basic_auth; /* did we send a client secret? */
- bool debugging; /* can we give unsafe developer assistance? */
+ oauth_debug_flags debug_flags; /* can we give developer assistance */
int dbg_num_calls; /* (debug mode) how many times were we called? */
};
@@ -1023,7 +1023,7 @@ parse_interval(struct async_ctx *actx, const char *interval_str)
parsed = ceil(parsed);
if (parsed < 1)
- return actx->debugging ? 0 : 1;
+ return actx->debug_flags.fast_retry ? 0 : 1;
else if (parsed >= INT_MAX)
return INT_MAX;
@@ -1797,7 +1797,7 @@ setup_curl_handles(struct async_ctx *actx)
*/
CHECK_SETOPT(actx, CURLOPT_NOSIGNAL, 1L, return false);
- if (actx->debugging)
+ if (actx->debug_flags.trace)
{
/*
* Set a callback for retrieving error information from libcurl, the
@@ -1829,7 +1829,7 @@ setup_curl_handles(struct async_ctx *actx)
const long unsafe = CURLPROTO_HTTPS | CURLPROTO_HTTP;
#endif
- if (actx->debugging)
+ if (actx->debug_flags.http)
protos = unsafe;
CHECK_SETOPT(actx, popt, protos, return false);
@@ -2297,7 +2297,7 @@ check_for_device_flow(struct async_ctx *actx)
* decent time to bail out if we're not using HTTPS for the endpoints
* we'll use for the flow.
*/
- if (!actx->debugging)
+ if (!actx->debug_flags.http)
{
if (pg_strncasecmp(provider->device_authorization_endpoint,
HTTPS_SCHEME, strlen(HTTPS_SCHEME)) != 0)
@@ -3027,7 +3027,7 @@ pg_fe_run_oauth_flow(PGconn *conn, struct PGoauthBearerRequest *request,
* drain_timer_events(), when we're in debug mode, track the total number
* of calls to this function and print that at the end of the flow.
*/
- if (actx->debugging)
+ if (actx && actx->debug_flags.poll_counts)
{
actx->dbg_num_calls++;
if (result == PGRES_POLLING_OK || result == PGRES_POLLING_FAILED)
@@ -3087,8 +3087,8 @@ pg_start_oauthbearer(PGconn *conn, PGoauthBearerRequestV2 *request)
* Now finish filling in the actx.
*/
- /* Should we enable unsafe features? */
- actx->debugging = oauth_unsafe_debugging_enabled();
+ /* Parse debug flags from the environment. */
+ actx->debug_flags = oauth_get_debug_flags();
initPQExpBuffer(&actx->work_data);
initPQExpBuffer(&actx->errbuf);
diff --git a/src/interfaces/libpq-oauth/oauth-utils.c b/src/interfaces/libpq-oauth/oauth-utils.c
index ccb0d9bf2c5..004d41f02aa 100644
--- a/src/interfaces/libpq-oauth/oauth-utils.c
+++ b/src/interfaces/libpq-oauth/oauth-utils.c
@@ -75,17 +75,6 @@ libpq_gettext(const char *msgid)
#endif /* ENABLE_NLS */
-/*
- * Returns true if the PGOAUTHDEBUG=UNSAFE flag is set in the environment.
- */
-bool
-oauth_unsafe_debugging_enabled(void)
-{
- const char *env = getenv("PGOAUTHDEBUG");
-
- return (env && strcmp(env, "UNSAFE") == 0);
-}
-
/*
* Duplicate SOCK_ERRNO* definitions from libpq-int.h, for use by
* pq_block/reset_sigpipe().
diff --git a/src/interfaces/libpq-oauth/test-oauth-curl.c b/src/interfaces/libpq-oauth/test-oauth-curl.c
index 4328a332738..06815be9a0a 100644
--- a/src/interfaces/libpq-oauth/test-oauth-curl.c
+++ b/src/interfaces/libpq-oauth/test-oauth-curl.c
@@ -89,7 +89,11 @@ init_test_actx(void)
actx->mux = PGINVALID_SOCKET;
actx->timerfd = -1;
- actx->debugging = true;
+ actx->debug_flags.http = true;
+ actx->debug_flags.trace = true;
+ actx->debug_flags.fast_retry = true;
+ actx->debug_flags.poll_counts = true;
+ actx->debug_flags.print_plugin_errors = true;
initPQExpBuffer(&actx->errbuf);
diff --git a/src/interfaces/libpq/fe-auth-oauth-debug.c b/src/interfaces/libpq/fe-auth-oauth-debug.c
new file mode 100644
index 00000000000..f9a1b1f195f
--- /dev/null
+++ b/src/interfaces/libpq/fe-auth-oauth-debug.c
@@ -0,0 +1,140 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe-auth-oauth-debug.c
+ * Parsing logic for PGOAUTHDEBUG environment variable
+ *
+ * This file contains pure string parsing logic with no dependencies on
+ * libpq or libpq-oauth implementation details. It's compiled into both
+ * libraries to avoid code duplication.
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/fe-auth-oauth-debug.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "fe-auth-oauth.h"
+
+/*
+ * Parse a single debug option from PGOAUTHDEBUG.
+ * Returns true if the option is recognized, false otherwise.
+ * Sets *is_unsafe to indicate if this option requires the UNSAFE: prefix.
+ */
+static bool
+parse_debug_option(const char *option, oauth_debug_flags *flags, bool *is_unsafe)
+{
+ *is_unsafe = false;
+
+ /* Unsafe options */
+ if (strcmp(option, "http") == 0)
+ {
+ flags->http = true;
+ *is_unsafe = true;
+ return true;
+ }
+ else if (strcmp(option, "trace") == 0)
+ {
+ flags->trace = true;
+ *is_unsafe = true;
+ return true;
+ }
+ /* Safe options */
+ else if (strcmp(option, "fast-retry") == 0)
+ {
+ flags->fast_retry = true;
+ return true;
+ }
+ else if (strcmp(option, "poll-counts") == 0)
+ {
+ flags->poll_counts = true;
+ return true;
+ }
+ else if (strcmp(option, "print-plugin-errors") == 0)
+ {
+ flags->print_plugin_errors = true;
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Parses the PGOAUTHDEBUG environment variable and returns debug flags.
+ *
+ * Supported formats:
+ * PGOAUTHDEBUG=UNSAFE - legacy format, enables all features
+ * PGOAUTHDEBUG=option1,option2 - enable safe features only
+ * PGOAUTHDEBUG=UNSAFE:opt1,opt2 - enable unsafe and/or safe features
+ *
+ * Prints a warning and skips the invalid option if:
+ * - An unrecognized option is specified
+ * - An unsafe option is specified without the UNSAFE: prefix
+ */
+oauth_debug_flags
+oauth_get_debug_flags(void)
+{
+ oauth_debug_flags flags = {0};
+ const char *env = getenv("PGOAUTHDEBUG");
+ char *options_str;
+ char *option;
+ char *saveptr = NULL;
+ bool unsafe_prefix = false;
+
+ if (!env || env[0] == '\0')
+ return flags;
+
+ if (strcmp(env, "UNSAFE") == 0)
+ {
+ flags.http = true;
+ flags.trace = true;
+ flags.fast_retry = true;
+ flags.poll_counts = true;
+ flags.print_plugin_errors = true;
+ return flags;
+ }
+
+ if (strncmp(env, "UNSAFE:", 7) == 0)
+ {
+ unsafe_prefix = true;
+ env += 7;
+ }
+
+ options_str = strdup(env);
+ if (!options_str)
+ return flags;
+
+ option = strtok_r(options_str, ",", &saveptr);
+ while (option != NULL)
+ {
+ bool is_unsafe;
+
+ if (!parse_debug_option(option, &flags, &is_unsafe))
+ {
+ fprintf(stderr,
+ "WARNING: PGOAUTHDEBUG: unrecognized debug option \"%s\" (ignored)\n",
+ option);
+ }
+ else if (is_unsafe && !unsafe_prefix)
+ {
+ fprintf(stderr,
+ "WARNING: PGOAUTHDEBUG: unsafe option \"%s\" requires UNSAFE: prefix (ignored)\n"
+ "Use: PGOAUTHDEBUG=UNSAFE:%s\n",
+ option, option);
+ }
+
+ option = strtok_r(NULL, ",", &saveptr);
+ }
+
+ free(options_str);
+
+ return flags;
+}
diff --git a/src/interfaces/libpq/fe-auth-oauth.c b/src/interfaces/libpq/fe-auth-oauth.c
index f93184f04db..4bfe31b03cb 100644
--- a/src/interfaces/libpq/fe-auth-oauth.c
+++ b/src/interfaces/libpq/fe-auth-oauth.c
@@ -383,7 +383,7 @@ issuer_from_well_known_uri(PGconn *conn, const char *wkuri)
authority_start = wkuri + strlen(HTTPS_SCHEME);
if (!authority_start
- && oauth_unsafe_debugging_enabled()
+ && oauth_get_debug_flags().http
&& pg_strncasecmp(wkuri, HTTP_SCHEME, strlen(HTTP_SCHEME)) == 0)
{
/* Allow http:// for testing only. */
@@ -897,7 +897,7 @@ use_builtin_flow(PGconn *conn, fe_oauth_state *state, PGoauthBearerRequestV2 *re
*
* Note that POSIX dlerror() isn't guaranteed to be threadsafe.
*/
- if (oauth_unsafe_debugging_enabled())
+ if (oauth_get_debug_flags().print_plugin_errors)
fprintf(stderr, "failed dlopen for libpq-oauth: %s\n", dlerror());
return 0;
@@ -911,7 +911,7 @@ use_builtin_flow(PGconn *conn, fe_oauth_state *state, PGoauthBearerRequestV2 *re
* cause is still locked behind PGOAUTHDEBUG due to the dlerror()
* threadsafety issue.
*/
- if (oauth_unsafe_debugging_enabled())
+ if (oauth_get_debug_flags().print_plugin_errors)
fprintf(stderr, "failed dlsym for libpq-oauth: %s\n", dlerror());
dlclose(state->builtin_flow);
@@ -1418,13 +1418,3 @@ pqClearOAuthToken(PGconn *conn)
conn->oauth_token = NULL;
}
-/*
- * Returns true if the PGOAUTHDEBUG=UNSAFE flag is set in the environment.
- */
-bool
-oauth_unsafe_debugging_enabled(void)
-{
- const char *env = getenv("PGOAUTHDEBUG");
-
- return (env && strcmp(env, "UNSAFE") == 0);
-}
--
2.34.1
[application/octet-stream] v2-0002-Add-new-PGOAUTHDEBUG-option-issuer-mismatch.patch (7.9K, 4-v2-0002-Add-new-PGOAUTHDEBUG-option-issuer-mismatch.patch)
download | inline diff:
From 933f6432f8743287977e9da99670c582b91275ae Mon Sep 17 00:00:00 2001
From: Zsolt Parragi <[email protected]>
Date: Wed, 18 Feb 2026 14:51:46 +0100
Subject: [PATCH v2 2/2] Add new PGOAUTHDEBUG option: issuer-mismatch
This new unsafe option allows to connection to proceed if the issuer
configured on the server and client mismatch, allowing to write
mismatched-issuer tests for validators.
Validators should test scenarios like this, as the wire allows this
situation, but previously libpq/psql prevented it, making writing tests
for this more difficult.
---
doc/src/sgml/libpq.sgml | 18 ++++++++++++++++--
src/interfaces/libpq/fe-auth-oauth.h | 1 +
src/interfaces/libpq-oauth/oauth-curl.c | 13 +++++++++----
src/interfaces/libpq-oauth/test-oauth-curl.c | 1 +
src/interfaces/libpq/fe-auth-oauth-debug.c | 7 +++++++
src/interfaces/libpq/fe-auth-oauth.c | 18 +++++++++++-------
.../modules/oauth_validator/t/001_server.pl | 15 +++++++++------
7 files changed, 54 insertions(+), 19 deletions(-)
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 2e5fb9011e9..172f8138546 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -10683,6 +10683,20 @@ PGOAUTHDEBUG=UNSAFE <lineannotation>legacy format; enables all options</linea
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>issuer-mismatch</literal> (unsafe)</term>
+ <listitem>
+ <para>
+ Tolerates a mismatch between the client's configured
+ <literal>oauth_issuer</literal> and the issuer found in the server's
+ discovery document. This disables the mix-up attack protection from
+ RFC 9207 and should only be used in development or testing environments
+ where the server's issuer identifier does not match the client
+ configuration.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><literal>fast-retry</literal> (safe)</term>
<listitem>
@@ -10718,8 +10732,8 @@ PGOAUTHDEBUG=UNSAFE <lineannotation>legacy format; enables all options</linea
</para>
<para>
- Unsafe options (<literal>http</literal>, <literal>trace</literal>)
- require the <literal>UNSAFE:</literal> prefix.
+ Unsafe options (<literal>http</literal>, <literal>trace</literal>,
+ <literal>issuer-mismatch</literal>) require the <literal>UNSAFE:</literal> prefix.
If unsafe options are specified without this prefix, a warning is printed
to standard error and that option is ignored. Other valid options in the
list continue to work. Safe options (<literal>fast-retry</literal>,
diff --git a/src/interfaces/libpq/fe-auth-oauth.h b/src/interfaces/libpq/fe-auth-oauth.h
index fde5c30c013..acc678f91cf 100644
--- a/src/interfaces/libpq/fe-auth-oauth.h
+++ b/src/interfaces/libpq/fe-auth-oauth.h
@@ -47,6 +47,7 @@ typedef struct oauth_debug_flags
/* UNSAFE features - require UNSAFE: prefix */
bool http; /* allow HTTP (unencrypted) connections */
bool trace; /* log HTTP traffic (exposes secrets) */
+ bool issuer_mismatch; /* tolerate issuer mismatch */
/* SAFE features - allowed without UNSAFE: prefix */
bool fast_retry; /* allow zero-second retry intervals */
diff --git a/src/interfaces/libpq-oauth/oauth-curl.c b/src/interfaces/libpq-oauth/oauth-curl.c
index 564d76cf063..5c18702da62 100644
--- a/src/interfaces/libpq-oauth/oauth-curl.c
+++ b/src/interfaces/libpq-oauth/oauth-curl.c
@@ -2249,10 +2249,15 @@ check_issuer(struct async_ctx *actx, PGconn *conn)
*/
if (strcmp(oauth_issuer_id, provider->issuer) != 0)
{
- actx_error(actx,
- "the issuer identifier (%s) does not match oauth_issuer (%s)",
- provider->issuer, oauth_issuer_id);
- return false;
+ if (!actx->debug_flags.issuer_mismatch)
+ {
+ actx_error(actx,
+ "the issuer identifier (%s) does not match oauth_issuer (%s)",
+ provider->issuer, oauth_issuer_id);
+ return false;
+ }
+
+ return true;
}
return true;
diff --git a/src/interfaces/libpq-oauth/test-oauth-curl.c b/src/interfaces/libpq-oauth/test-oauth-curl.c
index 06815be9a0a..776eaaafc8d 100644
--- a/src/interfaces/libpq-oauth/test-oauth-curl.c
+++ b/src/interfaces/libpq-oauth/test-oauth-curl.c
@@ -91,6 +91,7 @@ init_test_actx(void)
actx->timerfd = -1;
actx->debug_flags.http = true;
actx->debug_flags.trace = true;
+ actx->debug_flags.issuer_mismatch = true;
actx->debug_flags.fast_retry = true;
actx->debug_flags.poll_counts = true;
actx->debug_flags.print_plugin_errors = true;
diff --git a/src/interfaces/libpq/fe-auth-oauth-debug.c b/src/interfaces/libpq/fe-auth-oauth-debug.c
index f9a1b1f195f..309286e253f 100644
--- a/src/interfaces/libpq/fe-auth-oauth-debug.c
+++ b/src/interfaces/libpq/fe-auth-oauth-debug.c
@@ -47,6 +47,12 @@ parse_debug_option(const char *option, oauth_debug_flags *flags, bool *is_unsafe
*is_unsafe = true;
return true;
}
+ else if (strcmp(option, "issuer-mismatch") == 0)
+ {
+ flags->issuer_mismatch = true;
+ *is_unsafe = true;
+ return true;
+ }
/* Safe options */
else if (strcmp(option, "fast-retry") == 0)
{
@@ -96,6 +102,7 @@ oauth_get_debug_flags(void)
{
flags.http = true;
flags.trace = true;
+ flags.issuer_mismatch = true;
flags.fast_retry = true;
flags.poll_counts = true;
flags.print_plugin_errors = true;
diff --git a/src/interfaces/libpq/fe-auth-oauth.c b/src/interfaces/libpq/fe-auth-oauth.c
index 4bfe31b03cb..41340530f3e 100644
--- a/src/interfaces/libpq/fe-auth-oauth.c
+++ b/src/interfaces/libpq/fe-auth-oauth.c
@@ -606,13 +606,16 @@ handle_oauth_sasl_error(PGconn *conn, const char *msg, int msglen)
if (strcmp(conn->oauth_issuer_id, discovery_issuer) != 0)
{
- libpq_append_conn_error(conn,
- "server's discovery document at %s (issuer \"%s\") is incompatible with oauth_issuer (%s)",
- ctx.discovery_uri, discovery_issuer,
- conn->oauth_issuer_id);
+ if (!oauth_get_debug_flags().issuer_mismatch)
+ {
+ libpq_append_conn_error(conn,
+ "server's discovery document at %s (issuer \"%s\") is incompatible with oauth_issuer (%s)",
+ ctx.discovery_uri, discovery_issuer,
+ conn->oauth_issuer_id);
- free(discovery_issuer);
- goto cleanup;
+ free(discovery_issuer);
+ goto cleanup;
+ }
}
free(discovery_issuer);
@@ -625,7 +628,8 @@ handle_oauth_sasl_error(PGconn *conn, const char *msg, int msglen)
else
{
/* This must match the URI we'd previously determined. */
- if (strcmp(conn->oauth_discovery_uri, ctx.discovery_uri) != 0)
+ if (strcmp(conn->oauth_discovery_uri, ctx.discovery_uri) != 0
+ && !oauth_get_debug_flags().issuer_mismatch)
{
libpq_append_conn_error(conn,
"server's discovery document has moved to %s (previous location was %s)",
diff --git a/src/test/modules/oauth_validator/t/001_server.pl b/src/test/modules/oauth_validator/t/001_server.pl
index 9e4dba8c924..abe47154529 100644
--- a/src/test/modules/oauth_validator/t/001_server.pl
+++ b/src/test/modules/oauth_validator/t/001_server.pl
@@ -190,12 +190,15 @@ $node->connect_ok(
]);
# The issuer linked by the server must match the client's oauth_issuer setting.
-$node->connect_fails(
- "user=$user dbname=postgres oauth_issuer=$issuer oauth_client_id=f02c6361-0636",
- "oauth_issuer must match discovery",
- expected_stderr =>
- qr@server's discovery document at \Q$issuer/.well-known/oauth-authorization-server/alternate\E \(issuer "\Q$issuer/alternate\E"\) is incompatible with oauth_issuer \(\Q$issuer\E\)@
-);
+{
+ local $ENV{PGOAUTHDEBUG} = "UNSAFE:http";
+ $node->connect_fails(
+ "user=$user dbname=postgres oauth_issuer=$issuer oauth_client_id=f02c6361-0636",
+ "oauth_issuer must match discovery",
+ expected_stderr =>
+ qr@server's discovery document at \Q$issuer/.well-known/oauth-authorization-server/alternate\E \(issuer "\Q$issuer/alternate\E"\) is incompatible with oauth_issuer \(\Q$issuer\E\)@
+ );
+}
# Test require_auth settings against OAUTHBEARER.
my @cases = (
--
2.34.1
view thread (13+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected]
Subject: Re: [oauth] Split and extend PGOAUTHDEBUG
In-Reply-To: <CAOYmi+k_et3yXpJ8op71-95j7OYg-kX5bWLgW9YTV_5G7f+O1A@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox