Add SASL OAUTHBEARER support with application-supplied tokens#3694
Add SASL OAUTHBEARER support with application-supplied tokens#3694proddata wants to merge 2 commits into
Conversation
Add an oauthBearerToken client option for PostgreSQL OAUTHBEARER authentication, including token callback handling and SASL response serialization. Keep bearer tokens non-enumerable in client, connection parameters, and pool options, and document the new pure-JS client support. Add focused unit coverage for OAuth SASL mechanism selection, callback error paths, credential redaction, and SCRAM compatibility.
605f620 to
b19703e
Compare
brianc
left a comment
There was a problem hiding this comment.
This looks good to me. It would be nice if there was a way to configure a postgres instance w/ OAUTH authentication in CI so we could do an end-to-end integration test, but I realize configuring postgres in docker is somewhat non-trivial. Maybe ask an LLM to give that a shot? Otherwise this looks p straight forward and mergeable...ty!
I don't think there is a Postgres image with a bundled OAUTH validator module (yet). While Postgres does have some validators in the repo for tests https://github.com/postgres/postgres/tree/master/src/test/modules/oauth_validator, I think builidng Postgres for a test might be a bit much. So an approach would be to have some dummy validator and build it during testing and still use the same base Postgres docker image. However that likely means it should not be added to the CI, therefore added as separate workflow. Let me know what you think about it. |
This adds support for PostgreSQL's SASL
OAUTHBEARERauthentication mechanism when the application supplies a bearer token directly or through a callback.The implementation intentionally keeps OAuth provider interaction outside of
pg. OAuth bearer token acquisition depends heavily on the IdP, grant type, scopes, refresh behavior, caching policy, and user interaction model. Instead of embedding that logic in the driver, this change gives applications a focused hook for supplying a valid token whilepghandles the PostgreSQL SASL protocol exchange.Changes
oauthBearerTokenclient option that accepts either:OAUTHBEARERwhen the server advertises it andoauthBearerTokenis configured.sendSASLResponseMessageprotocol serializer while keepingsendSCRAMClientFinalMessageas an alias for SCRAM compatibility.oauthBearerTokennon-enumerable on client, connection parameters, and pool options so token values do not appear in common inspection/serialization output.Rationale
PostgreSQL 18 adds native OAuth authentication using the SASL
OAUTHBEARERmechanism. Returning a bearer token from the existingpasswordcallback is not sufficient because the server expects OAUTHBEARER SASL messages, not a SCRAM exchange.This change implements the PostgreSQL protocol support needed for callers that already have, or can fetch, a bearer token. Keeping token acquisition in user code keeps the driver small and avoids baking IdP-specific OAuth behavior into
pg.Scope
This does not implement a full OAuth authorization flow, device authorization grant, token discovery, or token refresh logic inside
pg.Applications can build those flows externally and provide the resulting token through
oauthBearerToken.This support applies to the pure JavaScript client.
pg.nativedelegates authentication to libpq and does not currently useoauthBearerToken; native OAuth support would require libpq OAuth configuration or new node-libpq auth hook bindings.Partially resolves #3687
I am not conviced that fully following libpq (oauth_issuer and oauth_client_id) is proper for a low level driver like node-pg. However open for suggestions.
co-authored with codex