Skip to content

#412 Add OAuth bearer token injection via PQsetAuthDataHook#447

Open
0814celsus wants to merge 1 commit intoduckdb:mainfrom
0814celsus:feat/pqsetauthdatahook-oauth-token-injection
Open

#412 Add OAuth bearer token injection via PQsetAuthDataHook#447
0814celsus wants to merge 1 commit intoduckdb:mainfrom
0814celsus:feat/pqsetauthdatahook-oauth-token-injection

Conversation

@0814celsus
Copy link
Copy Markdown

Implements the PG18 PQsetAuthDataHook API to inject OAuth bearer tokens during OAUTHBEARER authentication. This allows connecting to OAuth-enabled PostgreSQL servers with a pre-obtained token, bypassing the device authorization flow.

Token sources (checked in priority order):

  1. DuckDB setting: SET pg_oauth_token = ''
  2. Environment variable: PGOAUTHTOKEN

The hook is registered once at extension load time.
@staticlibs let me know if anything else is needed here?

Implements the PG18 PQsetAuthDataHook API to inject OAuth bearer tokens
during OAUTHBEARER authentication. This allows connecting to OAuth-enabled
PostgreSQL servers with a pre-obtained token, bypassing the device
authorization flow.

Token sources (checked in priority order):
1. DuckDB setting: SET pg_oauth_token = '<token>'
2. Environment variable: PGOAUTHTOKEN

The hook is registered once at extension load time.
@0814celsus
Copy link
Copy Markdown
Author

@staticlibs here is the Output from my console connection to my local postgres,

christoph@buero1:~/Projekte/duckdb-postgres$ TOKEN=$(curl -sk -X POST https://localhost:8443/realms/master/protocol/openid-connect/token
-d "grant_type=password&client_id=pg_oauth&client_secret=2Exlup9QmdFMoViZGzVD2PXEtfXkKaLT&username=admin&password=admin&scope=openid profile email" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
christoph@buero1:~/Projekte/duckdb-postgres$ PGOAUTHTOKEN="$TOKEN" ./build/reldebug/duckdb -unsigned
DuckDB v1.5.2 (Variegata)
Enter ".help" for usage hints.
memory D ATTACH 'host=127.0.0.1 port=5434 dbname=postgres user=admin oauth_issuer=https://localhost:8443/realms/master oauth_client_id=pg_oauth' AS pg_oauth (TYPE POSTGRES);
memory D SELECT * FROM postgres_query('pg_oauth', 'SELECT current_user');
┌──────────────┐
│ current_user │
│ varchar │
├──────────────┤
│ admin │
└──────────────┘
memory D `

@staticlibs
Copy link
Copy Markdown
Collaborator

Hi, thanks for the PR! I am a bit confused by the session state handling in it. For example, assuming we have 2 client threads that attach two different PG databases using OAuth for both of them. Each thread sets its own pg_oauth_token value, scoped to current user session (ClientContext in a Connection). Can such scenario be supported at all with PQsetAuthDataHook?

@0814celsus
Copy link
Copy Markdown
Author

@staticlibs
This is currently a limitation of this implementaion, Because the Hook itself is process-global. All threads/connections share the same token. Let me think about it. Probably there is a way to provide per connection token, I was focusing on my ducklake usecase which probably is the wrong focus for a extention wide implementaion,

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.

2 participants