Skip to content

Commit dee074c

Browse files
SNOW-2112179 token caching is disabled for Client Credentials OAuth flow (#2417)
1 parent 94afe8a commit dee074c

File tree

4 files changed

+25
-68
lines changed

4 files changed

+25
-68
lines changed

DESCRIPTION.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
99
# Release Notes
1010
- v3.16.1(TBD)
1111
- Added in-band OCSP exception telemetry.
12+
- Disabled token caching for OAuth Client Credentials authentication
1213
- Added in-band HTTP exception telemetry.
1314
- Fixed a bug where timezoned timestamps fetched as pandas.DataFrame or pyarrow.Table would overflow for the sake of unnecessary precision. In the case where an overflow cannot be prevented a clear error will be raised now.
1415

src/snowflake/connector/auth/oauth_credentials.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from typing import TYPE_CHECKING, Any
99

1010
from ..constants import OAUTH_TYPE_CLIENT_CREDENTIALS
11-
from ..token_cache import TokenCache
1211
from ._oauth_base import AuthByOAuthBase
1312

1413
if TYPE_CHECKING:
@@ -27,8 +26,6 @@ def __init__(
2726
client_secret: str,
2827
token_request_url: str,
2928
scope: str,
30-
token_cache: TokenCache | None = None,
31-
refresh_token_enabled: bool = False,
3229
connection: SnowflakeConnection | None = None,
3330
**kwargs,
3431
) -> None:
@@ -38,8 +35,8 @@ def __init__(
3835
client_secret=client_secret,
3936
token_request_url=token_request_url,
4037
scope=scope,
41-
token_cache=token_cache,
42-
refresh_token_enabled=refresh_token_enabled,
38+
token_cache=None,
39+
refresh_token_enabled=False,
4340
**kwargs,
4441
)
4542
self._application = application

src/snowflake/connector/connection.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,12 +1264,6 @@ def __open_connection(self):
12641264
host=self.host, port=self.port
12651265
),
12661266
scope=self._oauth_scope,
1267-
token_cache=(
1268-
auth.get_token_cache()
1269-
if self._client_store_temporary_credential
1270-
else None
1271-
),
1272-
refresh_token_enabled=self._oauth_enable_refresh_tokens,
12731267
connection=self,
12741268
)
12751269
elif self._authenticator == USR_PWD_MFA_AUTHENTICATOR:

test/unit/test_oauth_token.py

Lines changed: 22 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ def test_client_creds_successful_flow(
560560
wiremock_oauth_client_creds_dir,
561561
wiremock_generic_mappings_dir,
562562
monkeypatch,
563+
temp_cache,
563564
) -> None:
564565
wiremock_client.import_mapping(
565566
wiremock_oauth_client_creds_dir / "successful_flow.json"
@@ -570,6 +571,15 @@ def test_client_creds_successful_flow(
570571
wiremock_client.add_mapping(
571572
wiremock_generic_mappings_dir / "snowflake_disconnect_successful.json"
572573
)
574+
user = "testUser"
575+
access_token_key = TokenKey(
576+
user, wiremock_client.wiremock_host, TokenType.OAUTH_ACCESS_TOKEN
577+
)
578+
refresh_token_key = TokenKey(
579+
user, wiremock_client.wiremock_host, TokenType.OAUTH_REFRESH_TOKEN
580+
)
581+
temp_cache.store(access_token_key, "unused-access-token-123")
582+
temp_cache.store(refresh_token_key, "unused-refresh-token-123")
573583
with mock.patch("secrets.token_urlsafe", return_value="abc123"):
574584
cnx = snowflake.connector.connect(
575585
user="testUser",
@@ -582,10 +592,17 @@ def test_client_creds_successful_flow(
582592
oauth_token_request_url=f"http://{wiremock_client.wiremock_host}:{wiremock_client.wiremock_http_port}/oauth/token-request",
583593
host=wiremock_client.wiremock_host,
584594
port=wiremock_client.wiremock_http_port,
595+
oauth_enable_refresh_tokens=True,
596+
client_store_temporary_credential=True,
585597
)
586598

587599
assert cnx, "invalid cnx"
588600
cnx.close()
601+
# cached tokens are expected not to change since Client Credenials must not use token cache
602+
cached_access_token = temp_cache.retrieve(access_token_key)
603+
cached_refresh_token = temp_cache.retrieve(refresh_token_key)
604+
assert cached_access_token == "unused-access-token-123"
605+
assert cached_refresh_token == "unused-refresh-token-123"
589606

590607

591608
@pytest.mark.skipolddriver
@@ -626,58 +643,6 @@ def test_client_creds_token_request_error(
626643
)
627644

628645

629-
@pytest.mark.skipolddriver
630-
def test_client_creds_successful_refresh_token_flow(
631-
wiremock_client: WiremockClient,
632-
wiremock_oauth_refresh_token_dir,
633-
wiremock_generic_mappings_dir,
634-
monkeypatch,
635-
temp_cache,
636-
) -> None:
637-
wiremock_client.import_mapping(
638-
wiremock_generic_mappings_dir / "snowflake_login_failed.json"
639-
)
640-
wiremock_client.add_mapping(
641-
wiremock_oauth_refresh_token_dir / "refresh_successful.json"
642-
)
643-
wiremock_client.add_mapping(
644-
wiremock_generic_mappings_dir / "snowflake_login_successful.json"
645-
)
646-
wiremock_client.add_mapping(
647-
wiremock_generic_mappings_dir / "snowflake_disconnect_successful.json"
648-
)
649-
user = "testUser"
650-
access_token_key = TokenKey(
651-
user, wiremock_client.wiremock_host, TokenType.OAUTH_ACCESS_TOKEN
652-
)
653-
refresh_token_key = TokenKey(
654-
user, wiremock_client.wiremock_host, TokenType.OAUTH_REFRESH_TOKEN
655-
)
656-
temp_cache.store(access_token_key, "expired-access-token-123")
657-
temp_cache.store(refresh_token_key, "refresh-token-123")
658-
cnx = snowflake.connector.connect(
659-
user=user,
660-
authenticator="OAUTH_CLIENT_CREDENTIALS",
661-
oauth_client_id="123",
662-
account="testAccount",
663-
protocol="http",
664-
role="ANALYST",
665-
oauth_client_secret="testClientSecret",
666-
oauth_token_request_url=f"http://{wiremock_client.wiremock_host}:{wiremock_client.wiremock_http_port}/oauth/token-request",
667-
host=wiremock_client.wiremock_host,
668-
port=wiremock_client.wiremock_http_port,
669-
oauth_enable_refresh_tokens=True,
670-
client_store_temporary_credential=True,
671-
)
672-
assert cnx, "invalid cnx"
673-
cnx.close()
674-
675-
new_access_token = temp_cache.retrieve(access_token_key)
676-
new_refresh_token = temp_cache.retrieve(refresh_token_key)
677-
assert new_access_token == "access-token-123"
678-
assert new_refresh_token == "refresh-token-123"
679-
680-
681646
@pytest.mark.skipolddriver
682647
def test_client_creds_expired_refresh_token_flow(
683648
wiremock_client: WiremockClient,
@@ -729,8 +694,8 @@ def test_client_creds_expired_refresh_token_flow(
729694
)
730695
assert cnx, "invalid cnx"
731696
cnx.close()
732-
733-
new_access_token = temp_cache.retrieve(access_token_key)
734-
new_refresh_token = temp_cache.retrieve(refresh_token_key)
735-
assert new_access_token == "access-token-123"
736-
assert new_refresh_token == "refresh-token-123"
697+
# the cache state is expected not to change, since Client Credentials must not use token caching
698+
cached_access_token = temp_cache.retrieve(access_token_key)
699+
cached_refresh_token = temp_cache.retrieve(refresh_token_key)
700+
assert cached_access_token == "expired-access-token-123"
701+
assert cached_refresh_token == "expired-refresh-token-123"

0 commit comments

Comments
 (0)