[PECOBLR-2089] fix(rust/oauth): Test suite fixes from final validation#324
[PECOBLR-2089] fix(rust/oauth): Test suite fixes from final validation#324vikrantpuppala wants to merge 20 commits intoadbc-drivers:mainfrom
Conversation
Design for OAuth 2.0 authentication in the Rust ADBC driver covering Authorization Code + PKCE (U2M) and Client Credentials (M2M) flows, including token refresh state machine, file-based caching, and OIDC discovery. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use oauth2 crate for PKCE, token exchange, client credentials, and refresh token flows. Eliminates hand-rolled pkce.rs module. - Reuse DatabricksHttpClient for token endpoint calls via execute_without_auth(), giving unified retry/timeout/pooling. - Two-phase initialization: HTTP client created first, auth provider set later via OnceLock (matching SeaClient's reader_factory pattern). - OAuth providers route token requests through the shared HTTP client with a custom oauth2 HTTP function adapter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add AuthMechanism enum: 0=Pat, 11=OAuth (matches ODBC AuthMech) - Add AuthFlow enum: 0=TokenPassthrough, 1=ClientCredentials, 2=Browser (matches ODBC Auth_Flow) - Both mechanism and flow are mandatory, no auto-detection - Accept numeric values only, parsed via TryFrom - Use unified DatabricksHttpClient with two-phase init - Adopt oauth2 crate for protocol-level operations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes: - databricks.oauth.token_endpoint -> databricks.auth.token_endpoint - Config type Int/String -> Int (numeric only) - Clarify oauth2 HTTP adapter needs thin conversion layer - Architecture diagram shows M2M/U2M using execute_without_auth() - Token passthrough (flow=0) documents no auto-refresh - Stale threshold uses initial_TTL computed once at acquisition - Deduplicate http.rs changes (reference Concurrency section) Test strategy additions: - Wiremock integration tests for full M2M flow with mocked HTTP - Database config validation tests for enum parsing and new_connection - HTTP client two-phase init tests for OnceLock lifecycle Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3-task breakdown covering foundation + HTTP client changes, M2M provider, and U2M provider with full test coverage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-1.1-oauth-token-struct
…D: task-1.4-token-store
727b177 to
0e69f4a
Compare
rust/src/auth/oauth/cache.rs
Outdated
| scopes: Vec<String>, | ||
| } | ||
|
|
||
| #[allow(dead_code)] // Used in Phase 3 (U2M) |
There was a problem hiding this comment.
why this? i think this is used now? we should fix all such instances across
| <p>You can close this tab and return to your application.</p> | ||
| </div> | ||
| </body> | ||
| </html>"#; |
There was a problem hiding this comment.
let's make this page simpler, no need for fancy fonts colours, check marks, etc.
| <p>An error occurred during authentication. You can close this tab and try again.</p> | ||
| </div> | ||
| </body> | ||
| </html>"#; |
There was a problem hiding this comment.
use simple pages
| // Use block_in_place to avoid blocking the runtime if we're in one, | ||
| // and get the handle to block_on the async operation | ||
| tokio::task::block_in_place(|| { | ||
| tokio::runtime::Handle::current().block_on(async { |
There was a problem hiding this comment.
shouldn't this happen async? check all instances and see if we're handling this correctly
rust/src/auth/oauth.rs.old
Outdated
There was a problem hiding this comment.
should we just remove this?
rust/src/database.rs
Outdated
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| #[repr(u8)] | ||
| pub enum AuthMechanism { | ||
| /// Personal access token (no OAuth). Config value: 0 | ||
| Pat = 0, | ||
| /// OAuth 2.0 -- requires AuthFlow to select the specific flow. Config value: 11 | ||
| OAuth = 11, | ||
| } | ||
|
|
||
| impl TryFrom<i64> for AuthMechanism { | ||
| type Error = crate::error::Error; | ||
|
|
||
| fn try_from(value: i64) -> std::result::Result<Self, Self::Error> { | ||
| match value { | ||
| 0 => Ok(AuthMechanism::Pat), | ||
| 11 => Ok(AuthMechanism::OAuth), | ||
| _ => Err(DatabricksErrorHelper::invalid_argument().message(format!( | ||
| "Invalid auth mechanism value: {}. Valid values are 0 (PAT) or 11 (OAuth)", | ||
| value | ||
| ))), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// OAuth authentication flow -- selects the specific OAuth grant type. | ||
| /// Config values match the ODBC driver's Auth_Flow numeric codes. | ||
| /// Only applicable when AuthMechanism is OAuth. | ||
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
| #[repr(u8)] | ||
| pub enum AuthFlow { | ||
| /// Use a pre-obtained OAuth access token directly. Config value: 0 | ||
| TokenPassthrough = 0, | ||
| /// M2M: client credentials grant for service principals. Config value: 1 | ||
| ClientCredentials = 1, | ||
| /// U2M: browser-based authorization code + PKCE. Config value: 2 | ||
| Browser = 2, | ||
| } | ||
|
|
||
| impl TryFrom<i64> for AuthFlow { | ||
| type Error = crate::error::Error; | ||
|
|
||
| fn try_from(value: i64) -> std::result::Result<Self, Self::Error> { | ||
| match value { | ||
| 0 => Ok(AuthFlow::TokenPassthrough), | ||
| 1 => Ok(AuthFlow::ClientCredentials), | ||
| 2 => Ok(AuthFlow::Browser), | ||
| _ => Err(DatabricksErrorHelper::invalid_argument().message(format!( | ||
| "Invalid auth flow value: {}. Valid values are 0 (token passthrough), 1 (client credentials), or 2 (browser)", | ||
| value | ||
| ))), | ||
| } | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
is this the right place to define this? seems like database is becoming bloated?
There was a problem hiding this comment.
overall would be great if we can abstract out the auth related stuff in this file so that it is less bloated
rust/CLAUDE.md
Outdated
| - Test names: `test_<function>_<scenario>` | ||
| - E2E tests that require real Databricks connection should be marked with `#[ignore]` | ||
|
|
||
| #### Running E2E OAuth Tests |
There was a problem hiding this comment.
don't think we need this section
0e69f4a to
13f8c28
Compare
…task-1.5-oauth-module-setup
…: task-2.2-database-config-fields
…2.3-database-validation
…1-callback-server
…sk-3.2-u2m-provider
…3-database-integration
…task-4.1-wiremock-u2m-refresh
…sk ID: task-4.2-m2m-database-integration
13f8c28 to
f87df69
Compare
🥞 Stacked PR
Use this link to review incremental changes.
Summary
Minor fixes discovered while running the full test suite:
AuthConfigconsistently