Skip to content

Navigation Menu

Sign in
Sign up

SNOW-4036712: OAuth Authorization Code flow replaces custom public PKCE client_id with LOCAL_APPLICATION #3011

Open
Labels
bug status-triage_doneInitial triage done, will be further handled by the driver team

Description

Python version

Python 3.12.12 (main, Jan 27 2026, 23:41:44) [Clang 21.1.4]

Operating system and processor architecture

macOS-26.6.2-arm64-arm-64bit

Installed packages

annotated-doc==0.0.5
annotated-types==0.8.0
anyio==4.14.2
asn1crypto==1.5.1
attrs==26.1.0
boto3==1.43.79
botocore==1.43.79
certifi==2026.7.22
cffi==2.1.1
charset-normalizer==3.5.1
click==8.4.2
cryptography==50.0.1
filelock==3.32.4
h11==0.16.0
httpcore==1.0.9
httpcore2==2.12.0
httpx==0.28.1
httpx-sse==0.4.3
httpx2==2.12.0
idna==3.19
keyring==25.7.0
mcp==2.1.1
mcp-types==2.1.1
packaging==26.3
pydantic==2.13.4
pyjwt==2.13.0
pyopenssl==26.4.0
pytest==9.1.1
python-dateutil==2.9.0.post0
requests==2.34.2
snowflake-connector-python==4.7.2
typing-extensions==4.16.0
urllib3==2.7.0

What did you do?

I configured Authorization Code OAuth with PKCE using a Snowflake custom OAuth integration registered as a public client. Public clients have a client_id but no client_secret.
Minimal reproducer:
from snowflake.connector.auth.oauth_code import AuthByOauthCode
requested_client_id = "custom-public-client-id"
auth = AuthByOauthCode(
 application="reproducer",
 client_id=requested_client_id,
 client_secret=None,
 authentication_url=(
 "https://example.snowflakecomputing.com/oauth/authorize"
 ),
 token_request_url=(
 "https://example.snowflakecomputing.com/oauth/token-request"
 ),
 redirect_uri="http://127.0.0.1:8730/",
 scope="session:role:TEST_ROLE",
 host="example.snowflakecomputing.com",
)
print("requested client_id:", requested_client_id)
print("effective client_id:", auth._client_id)
print("effective client_secret:", auth._client_secret)
Output:
requested client_id: custom-public-client-id
effective client_id: LOCAL_APPLICATION
effective client_secret: LOCAL_APPLICATION
`AuthByOauthCode._eligible_for_default_client_credentials()` considers the configuration eligible for default credentials whenever `client_secret` is None, even when a nonempty custom `client_id` was supplied.
Using a dummy nonempty secret is not a valid workaround because the connector transmits it through HTTP Basic authentication.
I reproduced the same behavior in connector versions 3.18.0 through 4.7.2.
Using client_secret="" instead fails with:

What did you expect to see?

For an Authorization Code + PKCE public client, the connector should:

  • Preserve the supplied custom client_id.
  • Permit an absent client secret.
  • Include client_id in the token request form.
  • Omit the HTTP Basic Authorization header.

Instead, the connector silently replaces both values with LOCAL_APPLICATION. This authenticates against the wrong Snowflake OAuth integration and can also reuse tokens cached for that integration.

Can you set logging to DEBUG and collect the logs?

2026年08月28日 15:59:01,506 DEBUG snowflake.connector.auth.oauth_code chose oauth state: **********************************************************
2026年08月28日 15:59:01,506 DEBUG snowflake.connector.auth.oauth_code oauth pkce is going to be used
requested client_id: custom-public-client-id
effective client_id: LOCAL_APPLICATION
effective client_secret: LOCAL_APPLICATION

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bug status-triage_doneInitial triage done, will be further handled by the driver team

Type

No type

Projects

No projects

Milestone

No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    AltStyle によって変換されたページ (->オリジナル) /