]> begriffs open source - ai-pg/blob - full-docs/html/oauth-validator-design.html
Include latest toc output
[ai-pg] / full-docs / html / oauth-validator-design.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>50.1. Safely Designing a Validator Module</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="oauth-validators.html" title="Chapter 50. OAuth Validator Modules" /><link rel="next" href="oauth-validator-init.html" title="50.2. Initialization Functions" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">50.1. Safely Designing a Validator Module</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="oauth-validators.html" title="Chapter 50. OAuth Validator Modules">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="oauth-validators.html" title="Chapter 50. OAuth Validator Modules">Up</a></td><th width="60%" align="center">Chapter 50. OAuth Validator Modules</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="oauth-validator-init.html" title="50.2. Initialization Functions">Next</a></td></tr></table><hr /></div><div class="sect1" id="OAUTH-VALIDATOR-DESIGN"><div class="titlepage"><div><div><h2 class="title" style="clear: both">50.1. Safely Designing a Validator Module <a href="#OAUTH-VALIDATOR-DESIGN" class="id_link">#</a></h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="oauth-validator-design.html#OAUTH-VALIDATOR-DESIGN-RESPONSIBILITIES">50.1.1. Validator Responsibilities</a></span></dt><dt><span class="sect2"><a href="oauth-validator-design.html#OAUTH-VALIDATOR-DESIGN-GUIDELINES">50.1.2. General Coding Guidelines</a></span></dt><dt><span class="sect2"><a href="oauth-validator-design.html#OAUTH-VALIDATOR-DESIGN-USERMAP-DELEGATION">50.1.3. Authorizing Users (Usermap Delegation)</a></span></dt></dl></div><div class="warning"><h3 class="title">Warning</h3><p>
3     Read and understand the entirety of this section before implementing a
4     validator module. A malfunctioning validator is potentially worse than no
5     authentication at all, both because of the false sense of security it
6     provides, and because it may contribute to attacks against other pieces of
7     an OAuth ecosystem.
8    </p></div><div class="sect2" id="OAUTH-VALIDATOR-DESIGN-RESPONSIBILITIES"><div class="titlepage"><div><div><h3 class="title">50.1.1. Validator Responsibilities <a href="#OAUTH-VALIDATOR-DESIGN-RESPONSIBILITIES" class="id_link">#</a></h3></div></div></div><p>
9     Although different modules may take very different approaches to token
10     validation, implementations generally need to perform three separate
11     actions:
12    </p><div class="variablelist"><dl class="variablelist"><dt><span class="term">Validate the Token</span></dt><dd><p>
13        The validator must first ensure that the presented token is in fact a
14        valid Bearer token for use in client authentication. The correct way to
15        do this depends on the provider, but it generally involves either
16        cryptographic operations to prove that the token was created by a trusted
17        party (offline validation), or the presentation of the token to that
18        trusted party so that it can perform validation for you (online
19        validation).
20       </p><p>
21        Online validation, usually implemented via
22        <a class="ulink" href="https://datatracker.ietf.org/doc/html/rfc7662" target="_top">OAuth Token
23        Introspection</a>, requires fewer steps of a validator module and
24        allows central revocation of a token in the event that it is stolen
25        or misissued. However, it does require the module to make at least one
26        network call per authentication attempt (all of which must complete
27        within the configured <a class="xref" href="runtime-config-connection.html#GUC-AUTHENTICATION-TIMEOUT">authentication_timeout</a>).
28        Additionally, your provider may not provide introspection endpoints for
29        use by external resource servers.
30       </p><p>
31        Offline validation is much more involved, typically requiring a validator
32        to maintain a list of trusted signing keys for a provider and then
33        check the token's cryptographic signature along with its contents.
34        Implementations must follow the provider's instructions to the letter,
35        including any verification of issuer ("where is this token from?"),
36        audience ("who is this token for?"), and validity period ("when can this
37        token be used?"). Since there is no communication between the module and
38        the provider, tokens cannot be centrally revoked using this method;
39        offline validator implementations may wish to place restrictions on the
40        maximum length of a token's validity period.
41       </p><p>
42        If the token cannot be validated, the module should immediately fail.
43        Further authentication/authorization is pointless if the bearer token
44        wasn't issued by a trusted party.
45       </p></dd><dt><span class="term">Authorize the Client</span></dt><dd><p>
46        Next the validator must ensure that the end user has given the client
47        permission to access the server on their behalf. This generally involves
48        checking the scopes that have been assigned to the token, to make sure
49        that they cover database access for the current HBA parameters.
50       </p><p>
51        The purpose of this step is to prevent an OAuth client from obtaining a
52        token under false pretenses. If the validator requires all tokens to
53        carry scopes that cover database access, the provider should then loudly
54        prompt the user to grant that access during the flow. This gives them the
55        opportunity to reject the request if the client isn't supposed to be
56        using their credentials to connect to databases.
57       </p><p>
58        While it is possible to establish client authorization without explicit
59        scopes by using out-of-band knowledge of the deployed architecture, doing
60        so removes the user from the loop, which prevents them from catching
61        deployment mistakes and allows any such mistakes to be exploited
62        silently. Access to the database must be tightly restricted to only
63        trusted clients
64        <a href="#ftn.id-1.8.17.6.3.3.2.2.3.1" class="footnote"><sup class="footnote" id="id-1.8.17.6.3.3.2.2.3.1">[17]</sup></a>
65        if users are not prompted for additional scopes.
66       </p><p>
67        Even if authorization fails, a module may choose to continue to pull
68        authentication information from the token for use in auditing and
69        debugging.
70       </p></dd><dt><span class="term">Authenticate the End User</span></dt><dd><p>
71        Finally, the validator should determine a user identifier for the token,
72        either by asking the provider for this information or by extracting it
73        from the token itself, and return that identifier to the server (which
74        will then make a final authorization decision using the HBA
75        configuration). This identifier will be available within the session via
76        <a class="link" href="functions-info.html#FUNCTIONS-INFO-SESSION-TABLE" title="Table 9.71. Session Information Functions"><code class="function">system_user</code></a>
77        and recorded in the server logs if <a class="xref" href="runtime-config-logging.html#GUC-LOG-CONNECTIONS">log_connections</a>
78        is enabled.
79       </p><p>
80        Different providers may record a variety of different authentication
81        information for an end user, typically referred to as
82        <span class="emphasis"><em>claims</em></span>. Providers usually document which of these
83        claims are trustworthy enough to use for authorization decisions and
84        which are not. (For instance, it would probably not be wise to use an
85        end user's full name as the identifier for authentication, since many
86        providers allow users to change their display names arbitrarily.)
87        Ultimately, the choice of which claim (or combination of claims) to use
88        comes down to the provider implementation and application requirements.
89       </p><p>
90        Note that anonymous/pseudonymous login is possible as well, by enabling
91        usermap delegation; see
92        <a class="xref" href="oauth-validator-design.html#OAUTH-VALIDATOR-DESIGN-USERMAP-DELEGATION" title="50.1.3. Authorizing Users (Usermap Delegation)">Section 50.1.3</a>.
93       </p></dd></dl></div></div><div class="sect2" id="OAUTH-VALIDATOR-DESIGN-GUIDELINES"><div class="titlepage"><div><div><h3 class="title">50.1.2. General Coding Guidelines <a href="#OAUTH-VALIDATOR-DESIGN-GUIDELINES" class="id_link">#</a></h3></div></div></div><p>
94     Developers should keep the following in mind when implementing token
95     validation:
96    </p><div class="variablelist"><dl class="variablelist"><dt><span class="term">Token Confidentiality</span></dt><dd><p>
97        Modules should not write tokens, or pieces of tokens, into the server
98        log. This is true even if the module considers the token invalid; an
99        attacker who confuses a client into communicating with the wrong provider
100        should not be able to retrieve that (otherwise valid) token from the
101        disk.
102       </p><p>
103        Implementations that send tokens over the network (for example, to
104        perform online token validation with a provider) must authenticate the
105        peer and ensure that strong transport security is in use.
106       </p></dd><dt><span class="term">Logging</span></dt><dd><p>
107        Modules may use the same <a class="link" href="error-message-reporting.html" title="55.2. Reporting Errors Within the Server">logging
108        facilities</a> as standard extensions; however, the rules for emitting
109        log entries to the client are subtly different during the authentication
110        phase of the connection. Generally speaking, modules should log
111        verification problems at the <code class="symbol">COMMERROR</code> level and return
112        normally, instead of using <code class="symbol">ERROR</code>/<code class="symbol">FATAL</code>
113        to unwind the stack, to avoid leaking information to unauthenticated
114        clients.
115       </p></dd><dt><span class="term">Interruptibility</span></dt><dd><p>
116        Modules must remain interruptible by signals so that the server can
117        correctly handle authentication timeouts and shutdown signals from
118        <span class="application">pg_ctl</span>. For example, blocking calls on sockets
119        should generally be replaced with code that handles both socket events
120        and interrupts without races (see <code class="function">WaitLatchOrSocket()</code>,
121        <code class="function">WaitEventSetWait()</code>, et al), and long-running loops
122        should periodically call <code class="function">CHECK_FOR_INTERRUPTS()</code>.
123        Failure to follow this guidance may result in unresponsive backend
124        sessions.
125       </p></dd><dt><span class="term">Testing</span></dt><dd><p>
126        The breadth of testing an OAuth system is well beyond the scope of this
127        documentation, but at minimum, negative testing should be considered
128        mandatory. It's trivial to design a module that lets authorized users in;
129        the whole point of the system is to keep unauthorized users out.
130       </p></dd><dt><span class="term">Documentation</span></dt><dd><p>
131        Validator implementations should document the contents and format of the
132        authenticated ID that is reported to the server for each end user, since
133        DBAs may need to use this information to construct pg_ident maps. (For
134        instance, is it an email address? an organizational ID number? a UUID?)
135        They should also document whether or not it is safe to use the module in
136        <code class="symbol">delegate_ident_mapping=1</code> mode, and what additional
137        configuration is required in order to do so.
138       </p></dd></dl></div></div><div class="sect2" id="OAUTH-VALIDATOR-DESIGN-USERMAP-DELEGATION"><div class="titlepage"><div><div><h3 class="title">50.1.3. Authorizing Users (Usermap Delegation) <a href="#OAUTH-VALIDATOR-DESIGN-USERMAP-DELEGATION" class="id_link">#</a></h3></div></div></div><p>
139     The standard deliverable of a validation module is the user identifier,
140     which the server will then compare to any configured
141     <a class="link" href="auth-username-maps.html" title="20.2. User Name Maps"><code class="filename">pg_ident.conf</code>
142     mappings</a> and determine whether the end user is authorized to connect.
143     However, OAuth is itself an authorization framework, and tokens may carry
144     information about user privileges. For example, a token may be associated
145     with the organizational groups that a user belongs to, or list the roles
146     that a user may assume, and duplicating that knowledge into local usermaps
147     for every server may not be desirable.
148    </p><p>
149     To bypass username mapping entirely, and have the validator module assume
150     the additional responsibility of authorizing user connections, the HBA may
151     be configured with <a class="xref" href="auth-oauth.html#AUTH-OAUTH-DELEGATE-IDENT-MAPPING">delegate_ident_mapping</a>.
152     The module may then use token scopes or an equivalent method to decide
153     whether the user is allowed to connect under their desired role. The user
154     identifier will still be recorded by the server, but it plays no part in
155     determining whether to continue the connection.
156    </p><p>
157     Using this scheme, authentication itself is optional. As long as the module
158     reports that the connection is authorized, login will continue even if there
159     is no recorded user identifier at all. This makes it possible to implement
160     anonymous or pseudonymous access to the database, where the third-party
161     provider performs all necessary authentication but does not provide any
162     user-identifying information to the server. (Some providers may create an
163     anonymized ID number that can be recorded instead, for later auditing.)
164    </p><p>
165     Usermap delegation provides the most architectural flexibility, but it turns
166     the validator module into a single point of failure for connection
167     authorization. Use with caution.
168    </p></div><div class="footnotes"><br /><hr style="width:100; text-align:left;margin-left: 0" /><div id="ftn.id-1.8.17.6.3.3.2.2.3.1" class="footnote"><p><a href="#id-1.8.17.6.3.3.2.2.3.1" class="para"><sup class="para">[17] </sup></a>
169          That is, "trusted" in the sense that the OAuth client and the
170          <span class="productname">PostgreSQL</span> server are controlled by the same
171          entity. Notably, the Device Authorization client flow supported by
172          libpq does not usually meet this bar, since it's designed for use by
173          public/untrusted clients.
174         </p></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="oauth-validators.html" title="Chapter 50. OAuth Validator Modules">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="oauth-validators.html" title="Chapter 50. OAuth Validator Modules">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="oauth-validator-init.html" title="50.2. Initialization Functions">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 50. OAuth Validator Modules </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"> 50.2. Initialization Functions</td></tr></table></div></body></html>