]> begriffs open source - ai-pg/blob - full-docs/html/libpq-oauth.html
Include latest toc output
[ai-pg] / full-docs / html / libpq-oauth.html
1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>32.20. OAuth Support</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="libpq-ssl.html" title="32.19. SSL Support" /><link rel="next" href="libpq-threading.html" title="32.21. Behavior in Threaded Programs" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">32.20. OAuth Support</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="libpq-ssl.html" title="32.19. SSL Support">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="libpq.html" title="Chapter 32. libpq — C Library">Up</a></td><th width="60%" align="center">Chapter 32. <span class="application">libpq</span> — C Library</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="libpq-threading.html" title="32.21. Behavior in Threaded Programs">Next</a></td></tr></table><hr /></div><div class="sect1" id="LIBPQ-OAUTH"><div class="titlepage"><div><div><h2 class="title" style="clear: both">32.20. OAuth Support <a href="#LIBPQ-OAUTH" class="id_link">#</a></h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="libpq-oauth.html#LIBPQ-OAUTH-AUTHDATA-HOOKS">32.20.1. Authdata Hooks</a></span></dt><dt><span class="sect2"><a href="libpq-oauth.html#LIBPQ-OAUTH-DEBUGGING">32.20.2. Debugging and Developer Settings</a></span></dt></dl></div><p>
3    <span class="application">libpq</span> implements support for the OAuth v2 Device Authorization client flow,
4    documented in
5    <a class="ulink" href="https://datatracker.ietf.org/doc/html/rfc8628" target="_top">RFC 8628</a>,
6    as an optional module. See the <a class="link" href="install-make.html#CONFIGURE-OPTION-WITH-LIBCURL">
7    installation documentation</a> for information on how to enable support
8    for Device Authorization as a builtin flow.
9   </p><p>
10    When support is enabled and the optional module installed, <span class="application">libpq</span>
11    will use the builtin flow by default if the server
12    <a class="link" href="auth-oauth.html" title="20.15. OAuth Authorization/Authentication">requests a bearer token</a> during
13    authentication. This flow can be utilized even if the system running the
14    client application does not have a usable web browser, for example when
15    running a client via <acronym class="acronym">SSH</acronym>.
16   </p><p>
17    The builtin flow will, by default, print a URL to visit and a user code to
18    enter there:
19 </p><pre class="programlisting">
20 $ psql 'dbname=postgres oauth_issuer=https://example.com oauth_client_id=...'
21 Visit https://example.com/device and enter the code: ABCD-EFGH
22 </pre><p>
23    (This prompt may be
24    <a class="link" href="libpq-oauth.html#LIBPQ-OAUTH-AUTHDATA-PROMPT-OAUTH-DEVICE">customized</a>.)
25    The user will then log into their OAuth provider, which will ask whether
26    to allow libpq and the server to perform actions on their behalf. It is always
27    a good idea to carefully review the URL and permissions displayed, to ensure
28    they match expectations, before continuing. Permissions should not be given
29    to untrusted third parties.
30   </p><p>
31    Client applications may implement their own flows to customize interaction
32    and integration with applications. See <a class="xref" href="libpq-oauth.html#LIBPQ-OAUTH-AUTHDATA-HOOKS" title="32.20.1. Authdata Hooks">Section 32.20.1</a>
33    for more information on how add a custom flow to <span class="application">libpq</span>.
34   </p><p>
35    For an OAuth client flow to be usable, the connection string must at minimum
36    contain <a class="xref" href="libpq-connect.html#LIBPQ-CONNECT-OAUTH-ISSUER">oauth_issuer</a> and
37    <a class="xref" href="libpq-connect.html#LIBPQ-CONNECT-OAUTH-CLIENT-ID">oauth_client_id</a>. (These settings are
38    determined by your organization's OAuth provider.) The builtin flow
39    additionally requires the OAuth authorization server to publish a device
40    authorization endpoint.
41   </p><div class="note"><h3 class="title">Note</h3><p>
42     The builtin Device Authorization flow is not currently supported on Windows.
43     Custom client flows may still be implemented.
44    </p></div><div class="sect2" id="LIBPQ-OAUTH-AUTHDATA-HOOKS"><div class="titlepage"><div><div><h3 class="title">32.20.1. Authdata Hooks <a href="#LIBPQ-OAUTH-AUTHDATA-HOOKS" class="id_link">#</a></h3></div></div></div><p>
45     The behavior of the OAuth flow may be modified or replaced by a client using
46     the following hook API:
47
48     </p><div class="variablelist"><dl class="variablelist"><dt id="LIBPQ-PQSETAUTHDATAHOOK"><span class="term"><code class="function">PQsetAuthDataHook</code><a id="id-1.7.3.27.8.2.1.1.1.2" class="indexterm"></a></span> <a href="#LIBPQ-PQSETAUTHDATAHOOK" class="id_link">#</a></dt><dd><p>
49         Sets the <code class="symbol">PGauthDataHook</code>, overriding
50         <span class="application">libpq</span>'s handling of one or more aspects of
51         its OAuth client flow.
52 </p><pre class="synopsis">
53 void PQsetAuthDataHook(PQauthDataHook_type hook);
54 </pre><p>
55         If <em class="replaceable"><code>hook</code></em> is <code class="literal">NULL</code>, the
56         default handler will be reinstalled. Otherwise, the application passes
57         a pointer to a callback function with the signature:
58 </p><pre class="programlisting">
59 int hook_fn(PGauthData type, PGconn *conn, void *data);
60 </pre><p>
61         which <span class="application">libpq</span> will call when an action is
62         required of the application. <em class="replaceable"><code>type</code></em> describes
63         the request being made, <em class="replaceable"><code>conn</code></em> is the
64         connection handle being authenticated, and <em class="replaceable"><code>data</code></em>
65         points to request-specific metadata. The contents of this pointer are
66         determined by <em class="replaceable"><code>type</code></em>; see
67         <a class="xref" href="libpq-oauth.html#LIBPQ-OAUTH-AUTHDATA-HOOKS-TYPES" title="32.20.1.1. Hook Types">Section 32.20.1.1</a> for the supported
68         list.
69        </p><p>
70         Hooks can be chained together to allow cooperative and/or fallback
71         behavior. In general, a hook implementation should examine the incoming
72         <em class="replaceable"><code>type</code></em> (and, potentially, the request metadata
73         and/or the settings for the particular <em class="replaceable"><code>conn</code></em>
74         in use) to decide whether or not to handle a specific piece of authdata.
75         If not, it should delegate to the previous hook in the chain
76         (retrievable via <code class="function">PQgetAuthDataHook</code>).
77        </p><p>
78         Success is indicated by returning an integer greater than zero.
79         Returning a negative integer signals an error condition and abandons the
80         connection attempt. (A zero value is reserved for the default
81         implementation.)
82        </p></dd><dt id="LIBPQ-PQGETAUTHDATAHOOK"><span class="term"><code class="function">PQgetAuthDataHook</code><a id="id-1.7.3.27.8.2.1.2.1.2" class="indexterm"></a></span> <a href="#LIBPQ-PQGETAUTHDATAHOOK" class="id_link">#</a></dt><dd><p>
83         Retrieves the current value of <code class="symbol">PGauthDataHook</code>.
84 </p><pre class="synopsis">
85 PQauthDataHook_type PQgetAuthDataHook(void);
86 </pre><p>
87         At initialization time (before the first call to
88         <code class="function">PQsetAuthDataHook</code>), this function will return
89         <code class="symbol">PQdefaultAuthDataHook</code>.
90        </p></dd></dl></div><p>
91    </p><div class="sect3" id="LIBPQ-OAUTH-AUTHDATA-HOOKS-TYPES"><div class="titlepage"><div><div><h4 class="title">32.20.1.1. Hook Types <a href="#LIBPQ-OAUTH-AUTHDATA-HOOKS-TYPES" class="id_link">#</a></h4></div></div></div><p>
92      The following <code class="symbol">PGauthData</code> types and their corresponding
93      <em class="replaceable"><code>data</code></em> structures are defined:
94
95      </p><div class="variablelist"><dl class="variablelist"><dt id="LIBPQ-OAUTH-AUTHDATA-PROMPT-OAUTH-DEVICE"><span class="term">
96         <code class="symbol">PQAUTHDATA_PROMPT_OAUTH_DEVICE</code>
97         <a id="id-1.7.3.27.8.3.2.3.1.1.2" class="indexterm"></a>
98        </span> <a href="#LIBPQ-OAUTH-AUTHDATA-PROMPT-OAUTH-DEVICE" class="id_link">#</a></dt><dd><p>
99          Replaces the default user prompt during the builtin device
100          authorization client flow. <em class="replaceable"><code>data</code></em> points to
101          an instance of <code class="symbol">PGpromptOAuthDevice</code>:
102 </p><pre class="synopsis">
103 typedef struct _PGpromptOAuthDevice
104 {
105     const char *verification_uri;   /* verification URI to visit */
106     const char *user_code;          /* user code to enter */
107     const char *verification_uri_complete;  /* optional combination of URI and
108                                              * code, or NULL */
109     int         expires_in;         /* seconds until user code expires */
110 } PGpromptOAuthDevice;
111 </pre><p>
112         </p><p>
113          The OAuth Device Authorization flow which
114          <a class="link" href="install-make.html#CONFIGURE-OPTION-WITH-LIBCURL">can be included</a>
115          in <span class="application">libpq</span>
116          requires the end user to visit a URL with a browser, then enter a code
117          which permits <span class="application">libpq</span> to connect to the server
118          on their behalf. The default prompt simply prints the
119          <code class="literal">verification_uri</code> and <code class="literal">user_code</code>
120          on standard error. Replacement implementations may display this
121          information using any preferred method, for example with a GUI.
122         </p><p>
123          This callback is only invoked during the builtin device
124          authorization flow. If the application installs a
125          <a class="link" href="libpq-oauth.html#LIBPQ-OAUTH-AUTHDATA-OAUTH-BEARER-TOKEN">custom OAuth
126          flow</a>, or <span class="application">libpq</span> was not built with
127          support for the builtin flow, this authdata type will not be used.
128         </p><p>
129          If a non-NULL <code class="structfield">verification_uri_complete</code> is
130          provided, it may optionally be used for non-textual verification (for
131          example, by displaying a QR code). The URL and user code should still
132          be displayed to the end user in this case, because the code will be
133          manually confirmed by the provider, and the URL lets users continue
134          even if they can't use the non-textual method. For more information,
135          see section 3.3.1 in
136          <a class="ulink" href="https://datatracker.ietf.org/doc/html/rfc8628#section-3.3.1" target="_top">RFC 8628</a>.
137         </p></dd><dt id="LIBPQ-OAUTH-AUTHDATA-OAUTH-BEARER-TOKEN"><span class="term">
138         <code class="symbol">PQAUTHDATA_OAUTH_BEARER_TOKEN</code>
139         <a id="id-1.7.3.27.8.3.2.3.2.1.2" class="indexterm"></a>
140        </span> <a href="#LIBPQ-OAUTH-AUTHDATA-OAUTH-BEARER-TOKEN" class="id_link">#</a></dt><dd><p>
141          Adds a custom implementation of a flow, replacing the builtin flow if
142          it is <a class="link" href="install-make.html#CONFIGURE-OPTION-WITH-LIBCURL">installed</a>.
143          The hook should either directly return a Bearer token for the current
144          user/issuer/scope combination, if one is available without blocking, or
145          else set up an asynchronous callback to retrieve one.
146         </p><p>
147          <em class="replaceable"><code>data</code></em> points to an instance
148          of <code class="symbol">PGoauthBearerRequest</code>, which should be filled in
149          by the implementation:
150 </p><pre class="synopsis">
151 typedef struct PGoauthBearerRequest
152 {
153     /* Hook inputs (constant across all calls) */
154     const char *openid_configuration; /* OIDC discovery URL */
155     const char *scope;                /* required scope(s), or NULL */
156
157     /* Hook outputs */
158
159     /* Callback implementing a custom asynchronous OAuth flow. */
160     PostgresPollingStatusType (*async) (PGconn *conn,
161                                         struct PGoauthBearerRequest *request,
162                                         SOCKTYPE *altsock);
163
164     /* Callback to clean up custom allocations. */
165     void        (*cleanup) (PGconn *conn, struct PGoauthBearerRequest *request);
166
167     char       *token;   /* acquired Bearer token */
168     void       *user;    /* hook-defined allocated data */
169 } PGoauthBearerRequest;
170 </pre><p>
171         </p><p>
172          Two pieces of information are provided to the hook by
173          <span class="application">libpq</span>:
174          <em class="replaceable"><code>openid_configuration</code></em> contains the URL of an
175          OAuth discovery document describing the authorization server's
176          supported flows, and <em class="replaceable"><code>scope</code></em> contains a
177          (possibly empty) space-separated list of OAuth scopes which are
178          required to access the server. Either or both may be
179          <code class="literal">NULL</code> to indicate that the information was not
180          discoverable. (In this case, implementations may be able to establish
181          the requirements using some other preconfigured knowledge, or they may
182          choose to fail.)
183         </p><p>
184          The final output of the hook is <em class="replaceable"><code>token</code></em>, which
185          must point to a valid Bearer token for use on the connection. (This
186          token should be issued by the
187          <a class="xref" href="libpq-connect.html#LIBPQ-CONNECT-OAUTH-ISSUER">oauth_issuer</a> and hold the requested
188          scopes, or the connection will be rejected by the server's validator
189          module.) The allocated token string must remain valid until
190          <span class="application">libpq</span> is finished connecting; the hook
191          should set a <em class="replaceable"><code>cleanup</code></em> callback which will be
192          called when <span class="application">libpq</span> no longer requires it.
193         </p><p>
194          If an implementation cannot immediately produce a
195          <em class="replaceable"><code>token</code></em> during the initial call to the hook,
196          it should set the <em class="replaceable"><code>async</code></em> callback to handle
197          nonblocking communication with the authorization server.
198          <a href="#ftn.id-1.7.3.27.8.3.2.3.2.2.5.3" class="footnote"><sup class="footnote" id="id-1.7.3.27.8.3.2.3.2.2.5.3">[16]</sup></a>
199          This will be called to begin the flow immediately upon return from the
200          hook. When the callback cannot make further progress without blocking,
201          it should return either <code class="symbol">PGRES_POLLING_READING</code> or
202          <code class="symbol">PGRES_POLLING_WRITING</code> after setting
203          <code class="literal">*pgsocket</code> to the file descriptor that will be marked
204          ready to read/write when progress can be made again. (This descriptor
205          is then provided to the top-level polling loop via
206          <code class="function">PQsocket()</code>.) Return <code class="symbol">PGRES_POLLING_OK</code>
207          after setting <em class="replaceable"><code>token</code></em> when the flow is
208          complete, or <code class="symbol">PGRES_POLLING_FAILED</code> to indicate failure.
209         </p><p>
210          Implementations may wish to store additional data for bookkeeping
211          across calls to the <em class="replaceable"><code>async</code></em> and
212          <em class="replaceable"><code>cleanup</code></em> callbacks. The
213          <em class="replaceable"><code>user</code></em> pointer is provided for this purpose;
214          <span class="application">libpq</span> will not touch its contents and the
215          application may use it at its convenience. (Remember to free any
216          allocations during token cleanup.)
217         </p></dd></dl></div><p>
218     </p></div></div><div class="sect2" id="LIBPQ-OAUTH-DEBUGGING"><div class="titlepage"><div><div><h3 class="title">32.20.2. Debugging and Developer Settings <a href="#LIBPQ-OAUTH-DEBUGGING" class="id_link">#</a></h3></div></div></div><p>
219     A "dangerous debugging mode" may be enabled by setting the environment
220     variable <code class="envar">PGOAUTHDEBUG=UNSAFE</code>. This functionality is provided
221     for ease of local development and testing only. It does several things that
222     you will not want a production system to do:
223
224     </p><div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc; "><li class="listitem"><p>
225        permits the use of unencrypted HTTP during the OAuth provider exchange
226       </p></li><li class="listitem"><p>
227        allows the system's trusted CA list to be completely replaced using the
228        <code class="envar">PGOAUTHCAFILE</code> environment variable
229       </p></li><li class="listitem"><p>
230        prints HTTP traffic (containing several critical secrets) to standard
231        error during the OAuth flow
232       </p></li><li class="listitem"><p>
233        permits the use of zero-second retry intervals, which can cause the
234        client to busy-loop and pointlessly consume CPU
235       </p></li></ul></div><p>
236    </p><div class="warning"><h3 class="title">Warning</h3><p>
237      Do not share the output of the OAuth flow traffic with third parties. It
238      contains secrets that can be used to attack your clients and servers.
239     </p></div></div><div class="footnotes"><br /><hr style="width:100; text-align:left;margin-left: 0" /><div id="ftn.id-1.7.3.27.8.3.2.3.2.2.5.3" class="footnote"><p><a href="#id-1.7.3.27.8.3.2.3.2.2.5.3" class="para"><sup class="para">[16] </sup></a>
240            Performing blocking operations during the
241            <code class="symbol">PQAUTHDATA_OAUTH_BEARER_TOKEN</code> hook callback will
242            interfere with nonblocking connection APIs such as
243            <code class="function">PQconnectPoll</code> and prevent concurrent connections
244            from making progress. Applications which only ever use the
245            synchronous connection primitives, such as
246            <code class="function">PQconnectdb</code>, may synchronously retrieve a token
247            during the hook instead of implementing the
248            <em class="replaceable"><code>async</code></em> callback, but they will necessarily
249            be limited to one connection at a time.
250           </p></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="libpq-ssl.html" title="32.19. SSL Support">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="libpq.html" title="Chapter 32. libpq — C Library">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="libpq-threading.html" title="32.21. Behavior in Threaded Programs">Next</a></td></tr><tr><td width="40%" align="left" valign="top">32.19. SSL Support </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 18.0 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 32.21. Behavior in Threaded Programs</td></tr></table></div></body></html>