confluentinc / confluentinc/confluent-sql

Refreshing client-credentials BYOIDC

Open
#149 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
6
Forks
1
Avg merge
21h 47m
Merged PRs (30d)
26

Description

- **Goal:** reach parity with Flink Table API client PR-399's second OAuth mode — a self-refreshing external token sourced from the caller's IdP via client-credentials, so BYOIDC can sustain **long-running streaming** that outlives a single short-lived token (the gap child 1 documents but does not solve).
- **Surface:** new `connect()` params mirroring the plugin's option names — `external_token_url`, `external_client_id`, `external_client_secret`, `external_token_scope`. Mutually exclusive with the static `external_access_token` and with every API-key param. - **Scope (in):** a refreshing `httpx.Auth` for the `_flink_auth` slot built around an internal **token-source** member — a callable yielding a token *and* its expiry — that the refresh machinery (single-flight caching, proactive refresh ahead of expiry, forced re-fetch + one retry on HTTP 401) wraps uniformly. Child 2 ships the **canned** implementation of that source: an OAuth2 client-credentials grant against `external_token_url` (the driver reads `expires_in` off the grant response, which is what feeds proactive refresh). The #138 401→`OperationalError` translation is the fallback if refresh can't recover.
- **Out of scope:** any control-plane reach (still Flink-only); the Auth0 chain and everything in the sibling interactive epic.
- **Depends on:** child 1's `_flink_auth` seam.
- **Reference:** #399 `internal/ClientCredentialsTokenProvider` (the canned client-credentials
source) wrapped by `OAuthCredentialsProvider` (single-flight, 30s skew) + `OAuthTokenAuthenticator`
(`MAX_ATTEMPTS=2`, 401-driven refresh).
- **Sized right:** one new auth class + `connect()` wiring + tests; no new package, no threads
beyond the refresh single-flight, no control-plane surface.

> **Near-free follow-on (2b) — caller-supplied token source.** Because child 2 is built around the > internal token-source member above, exposing a *caller-supplied* implementation is a widening, not > a separate mechanism: the auth keeps the source as a data member and either instantiates its canned > client-credentials impl (given the config params) or defers to a callable the caller passes — the > refresh machinery is identical either way. This is exactly #399's factoring > (`OAuthCredentialsProvider` wraps some `OAuthTokenProvider`; `ClientCredentialsTokenProvider` is > the built-in one, a registered callback is the BYO one), and it covers non-standard sources — Azure > Managed Identity, AWS IAM workload identity, in-house token services. **The one added contract:** > for the BYO callable to get the same *proactive* refresh as the canned source it must surface a > token **plus** an expiry (#399's `OAuthToken(accessToken, expiresAt)`), not a bare `str` — a bare > string can only be refreshed reactively on 401. File it only when a concrete non-standard-source > demand surfaces; the seam it needs already exists from child 2.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start at the connect() entry point and the child 1 _flink_auth seam, then compare the referenced #399 ClientCredentialsTokenProvider, OAuthCredentialsProvider, and OAuthTokenAuthenticator. Define the auth class and connect() wiring around the listed external_* parameters, and add tests covering expiry refresh, single-flight behavior, one 401 retry, and configuration exclusivity.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
authentication, backend-api-design
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.