Skip to content

Commit 99bf619

Browse files
Fix SnowflakeRestful wrongly using PATWithExternalSessionAuth (#2454)
1 parent ac27d94 commit 99bf619

File tree

3 files changed

+62
-4
lines changed

3 files changed

+62
-4
lines changed

DESCRIPTION.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
1818
- Introduce snowflake_version property to the connection
1919
- Added basic json support for Interval types.
2020
- Moved `OAUTH_TYPE` to `CLIENT_ENVIROMENT`.
21+
- Fix bug where PAT with external session authenticator was used while `external_session_id` was not provided in `SnowflakeRestful.fetch`
2122

2223
- v3.16.0(July 04,2025)
2324
- Bumped numpy dependency from <2.1.0 to <=2.2.4.

src/snowflake/connector/network.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@
169169
PYTHON_CONNECTOR_USER_AGENT = f"{CLIENT_NAME}/{SNOWFLAKE_CONNECTOR_VERSION} ({PLATFORM}) {IMPLEMENTATION}/{PYTHON_VERSION}"
170170

171171
NO_TOKEN = "no-token"
172-
NO_EXTERNAL_SESSION_ID = "no-external-session-id"
173172

174173
STATUS_TO_EXCEPTION: dict[int, type[Error]] = {
175174
INTERNAL_SERVER_ERROR: InternalServerError,
@@ -332,7 +331,7 @@ def __call__(self, r: PreparedRequest) -> PreparedRequest:
332331
del r.headers[HEADER_AUTHORIZATION_KEY]
333332
if self.token != NO_TOKEN:
334333
r.headers[HEADER_AUTHORIZATION_KEY] = "Bearer " + self.token
335-
if self.external_session_id != NO_EXTERNAL_SESSION_ID:
334+
if self.external_session_id:
336335
r.headers[HEADER_EXTERNAL_SESSION_KEY] = self.external_session_id
337336
return r
338337

@@ -953,7 +952,7 @@ def _request_exec_wrapper(
953952
retry_ctx,
954953
no_retry: bool = False,
955954
token=NO_TOKEN,
956-
external_session_id=NO_EXTERNAL_SESSION_ID,
955+
external_session_id=None,
957956
**kwargs,
958957
):
959958
conn = self._connection

test/unit/test_network.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212

1313
try:
1414
from snowflake.connector import Error
15-
from snowflake.connector.network import SnowflakeRestful
15+
from snowflake.connector.network import (
16+
PATWithExternalSessionAuth,
17+
SnowflakeAuth,
18+
SnowflakeRestful,
19+
)
1620
from snowflake.connector.vendored.requests import HTTPError, Response
1721
except ImportError:
1822
# skipping old driver test
@@ -85,3 +89,57 @@ def test_json_serialize_uuid(u):
8589
assert (json.dumps(u, cls=SnowflakeRestfulJsonEncoder)) == f'"{u}"'
8690

8791
assert json.dumps({"u": u, "a": 42}, cls=SnowflakeRestfulJsonEncoder) == expected
92+
93+
94+
def test_fetch_auth():
95+
"""Test checks that PATWithExternalSessionAuth is used instead of SnowflakeAuth when external_session_id is provided."""
96+
connection = mock_connection()
97+
rest = SnowflakeRestful(
98+
host="test.snowflakecomputing.com", port=443, connection=connection
99+
)
100+
rest._token = "test-token"
101+
rest._master_token = "test-master-token"
102+
103+
captured_auth = None
104+
105+
def mock_request(**kwargs):
106+
nonlocal captured_auth
107+
captured_auth = kwargs.get("auth")
108+
mock_response = unittest.mock.MagicMock()
109+
mock_response.status_code = 200
110+
mock_response.json.return_value = {"success": True}
111+
return mock_response
112+
113+
with unittest.mock.patch(
114+
"snowflake.connector.network.requests.Session"
115+
) as mock_session_class:
116+
mock_session = unittest.mock.MagicMock()
117+
mock_session_class.return_value = mock_session
118+
mock_session.request = mock_request
119+
120+
# Call fetch without providing external_session_id - should use SnowflakeAuth
121+
rest.fetch(
122+
method="POST",
123+
full_url="https://test.snowflakecomputing.com/test",
124+
headers={},
125+
data={},
126+
)
127+
assert isinstance(captured_auth, SnowflakeAuth)
128+
129+
with unittest.mock.patch(
130+
"snowflake.connector.network.requests.Session"
131+
) as mock_session_class:
132+
mock_session = unittest.mock.MagicMock()
133+
mock_session_class.return_value = mock_session
134+
mock_session.request = mock_request
135+
136+
# Call fetch with providing external_session_id - should use PATWithExternalSessionAuth
137+
rest.fetch(
138+
method="POST",
139+
full_url="https://test.snowflakecomputing.com/test",
140+
headers={},
141+
data={},
142+
external_session_id="dummy-external-session-id",
143+
)
144+
assert isinstance(captured_auth, PATWithExternalSessionAuth)
145+
assert captured_auth.external_session_id == "dummy-external-session-id"

0 commit comments

Comments
 (0)