Skip to content

fix(rocky-snowflake): set auth-token-type header per auth mode#283

Merged
hugocorreia90 merged 1 commit intomainfrom
fix/snowflake-auth-token-type
Apr 29, 2026
Merged

fix(rocky-snowflake): set auth-token-type header per auth mode#283
hugocorreia90 merged 1 commit intomainfrom
fix/snowflake-auth-token-type

Conversation

@hugocorreia90
Copy link
Copy Markdown
Contributor

Summary

Snowflake's SQL REST API v2 connector hard-coded X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT on every request, even when the resolved auth mode was OAuth or password / session-token. For non-keypair users the warehouse rejected the request as an invalid JWT, the 401 retry path dropped the cache and re-minted the same wrong-typed token, and the loop kept failing — what looked like an auth/refresh problem was a header bug.

Bug

engine/crates/rocky-snowflake/src/connector.rs:344 (pre-fix) attached KEYPAIR_JWT unconditionally on submit. Poll and cancel paths sent no token-type header at all. Tests at tests/wiremock_tests.rs::test_bearer_token_sent encoded the broken assertion against an OAuth-configured connector — it passed only because the test mock never validated the token shape.

Fix

Per Snowflake's SQL API v2 auth docs:

Auth mode X-Snowflake-Authorization-Token-Type
Key-pair JWT (RS256) KEYPAIR_JWT
OAuth OAUTH
Password / session (omit — server sniffs from token)

Changes:

  • New pub enum auth::TokenType { KeypairJwt, OAuth, SessionToken } with a header_value() -> Option<&'static str> mapping.
  • New Auth::token_type() returning the resolved mode.
  • New SnowflakeConnector::apply_auth_headers() helper used by submit_and_wait_once, the polling loop, and cancel_statement — header logic now lives in one place and applies to every auth-bearing call site, not just submit.
  • prime_cache_with test helper on Auth is now pub under feature = "test-support" so integration tests can skip the JWT/login roundtrip.

Test plan

  • cargo test -p rocky-snowflake (107 unit tests pass)
  • cargo test -p rocky-snowflake --features test-support --test wiremock_tests (22/22 pass, including 3 new cases: test_oauth_auth_headers, test_keypair_auth_headers, test_password_auth_omits_token_type_header, plus test_token_type_header_mapping)
  • cargo clippy -p rocky-snowflake --all-targets --features test-support -- -D warnings clean
  • cargo fmt --check clean

Known follow-up (out of scope)

Snowflake's SQL API docs document the Authorization: Bearer <token> format for OAuth and key-pair, but session tokens minted via /session/v1/login-request are typically passed as Authorization: Snowflake Token="<token>". The connector still uses Bearer for all three modes — that is unchanged by this PR. Password mode was already broken before this change; tracking a follow-up.

…th mode

The connector hard-coded `X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT`
on every request, regardless of which auth mode was active. For OAuth and
password / session-token users this caused Snowflake to reject the request
as an invalid JWT, the connector's 401 retry path would drop the cache and
re-mint, and the same wrong-typed token would 401 again — burning retries
for what was, fundamentally, a header bug.

Per Snowflake's SQL API v2 spec
(https://docs.snowflake.com/en/developer-guide/sql-api/authenticating):

  Auth mode             | X-Snowflake-Authorization-Token-Type
  ----------------------|--------------------------------------
  Key-pair JWT (RS256)  | KEYPAIR_JWT
  OAuth                 | OAUTH
  Password / session    | (omit; server sniffs from token)

This adds a public `auth::TokenType` enum with a `header_value()` mapping,
exposes `Auth::token_type()`, and routes submit/poll/cancel through a
single `apply_auth_headers` helper so the same per-mode header logic
applies everywhere, not just submit. Three new wiremock tests assert the
correct header rides each auth mode.
@hugocorreia90 hugocorreia90 merged commit de3e8c8 into main Apr 29, 2026
12 checks passed
@hugocorreia90 hugocorreia90 deleted the fix/snowflake-auth-token-type branch April 29, 2026 16:44
hugocorreia90 added a commit that referenced this pull request Apr 29, 2026
Engine 1.18.0 ships the rocky preview workflow end-to-end (#279, #280,
#281, #282), the [budget].max_bytes_scanned threshold (#288), the
audit-sweep closeout (#283, #285#287, #290#293), and the rocky-server
auth + CORS gate (#291).

Dagster 1.15.0 picks up the regenerated Pydantic models for the rocky
preview surface and ships the P1 cluster (#289) + FR-014 follow-on
(#284).

VS Code 1.10.0 regenerates TypeScript bindings for rocky preview and
RunCostSummary.total_bytes_scanned.

See per-artifact CHANGELOG entries for the full breakdown.
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.

1 participant