Skip to content

Conversation

@Lilit0x
Copy link
Contributor

@Lilit0x Lilit0x commented Nov 12, 2025

Closes: #298
This PR adds OAuth 2.0 authentication support to pgwire using the SASL OAUTHBEARER mechanism. The implementation includes a pluggable OauthValidator trait that allows custom token validation logic, along with an almost production-grade Keycloak integration example that performs full JWT validation with RS256 signatures, OIDC discovery, and JWKS key caching.

@Lilit0x Lilit0x changed the title Postgres 18 OAuth #340 feat(server): #298 postgres 18 oauth support Nov 12, 2025
@Lilit0x Lilit0x marked this pull request as ready for review November 27, 2025 23:50
Copy link
Owner

@sunng87 sunng87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much @Lilit0x ! This is a major feature of pgwire and I hope you enjoyed it when implementing within the pgwire framework. I left some minor comments.

use std::sync::Arc;

use async_trait::async_trait;

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can reorganize the imports, first section for std, second section for other deps

@sunng87
Copy link
Owner

sunng87 commented Nov 28, 2025

By the way, do you know if it's possible to include some reusable validator implementation in pgwire?

match (state.is_oauth(), &res, &new_state) {
(true, Authentication::Ok, SASLState::Finished) => {
// we skip sending Authentication::Ok for OAuth because finish_authentication will send it
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need different workflow for oauth and scram here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the docs:

OAUTHBEARER does not support channel binding, and there is no "OAUTHBEARER-PLUS" mechanism. This mechanism does not make use of server data during a successful authentication, so the AuthenticationSASLFinal message is not used in the exchange.

Here, Oauth differs from SCRAM in the sense that we don't need to send SASLFinal after successful oauth validation, but we still need to return Authentication::Ok. The issue is that finish_authentication also returns Authentication::Ok, so, two success messages will be sent for Oauth. That's why I decided to skip sending the Authentication::Ok that process_oauth_message returns, just relying on the one that finish_authentication will send.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. By design, I was not going to return Authentication::Ok from these process_xxx_message methods. But in OAuth, there is no SASLFinal, so we will still need to return an Authentication variant here.

I think we can change process_oauth_message to return (Option<Authentication>, SASLState), so it will be clear to code readers.

@Lilit0x
Copy link
Contributor Author

Lilit0x commented Nov 28, 2025

By the way, do you know if it's possible to include some reusable validator implementation in pgwire?

Well, I can look into adding a simple JWT validator implementation.

use pgwire::api::auth::{DefaultServerParameterProvider, StartupHandler};
use pgwire::api::PgWireServerHandlers;
use pgwire::error::PgWireResult;
use pgwire::tokio::process_socket;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remember to reorder these imports

@sunng87
Copy link
Owner

sunng87 commented Nov 29, 2025

Well, I can look into adding a simple JWT validator implementation.

Thanks! This can be done in next patch.

Copy link
Owner

@sunng87 sunng87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Let me finish the last few changes.

@sunng87 sunng87 merged commit 3c2ef3b into sunng87:master Nov 30, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Postgres 18 OAuth authentication support

2 participants