snowflakedb / snowflakedb/snowflake-connector-python
SNOW-3560581: OAuth authorization code flow appends offline_access and causes invalid scope with Snowflake custom OAuth
@sfc-gh-snow-drivers-warsaw-dl is already working on this.
Since May 22, 2026.
- Dominant language
- Python
- Stars
- 730
- Forks
- 574
- Avg merge
- 5h 45m
- Merged PRs (30d)
- 16
Description
Summary
OAUTH_AUTHORIZATION_CODE with refresh-token reuse enabled appends offline_access to the authorization request scope. This causes Snowflake custom OAuth to fail with invalid_scope, because Snowflake custom OAuth documents refresh_token as the scope used to request offline access, not offline_access.
Environment
- Snowflake CLI:
3.18.0 - Bundled connector:
snowflake-connector-python 4.5.0 - OS: macOS
- Authenticator:
OAUTH_AUTHORIZATION_CODE - OAuth server: Snowflake custom OAuth security integration
Current behavior
With this connection config:
[connections.example]
account = "<account_identifier>"
user = "<user>"
warehouse = "<warehouse>"
role = "<role>"
authenticator = "OAUTH_AUTHORIZATION_CODE"
oauth_client_id = "<client id>"
oauth_client_secret = "<client secret>"
oauth_redirect_uri = "http://localhost:8001/snowflake/oauth-redirect"
oauth_scope = "refresh_token session:role:<ROLE>"
oauth_enable_refresh_tokens = true
oauth_enable_single_use_refresh_tokens = true
client_store_temporary_credential = true
The browser authorization request includes:
scope=refresh_token+session%3Arole%3A<ROLE>+offline_access
Snowflake then fails in the browser with:
Error occurred in authorization
The requested scope is invalid.
If I copy the failing request, remove the offline_access from scope string, it works as expected.
The security integration is configured to issue refresh tokens:
OAUTH_ISSUE_REFRESH_TOKENS = true
OAUTH_REFRESH_TOKEN_VALIDITY = <configured_validity>
OAUTH_SINGLE_USE_REFRESH_TOKENS_REQUIRED = true
OAUTH_ALLOW_NON_TLS_REDIRECT_URI = true
There does not appear to be a Snowflake OAuth custom-client integration parameter
that allows adding arbitrary accepted scopes such as offline_access.
Expected behavior
For Snowflake custom OAuth, enabling refresh-token reuse should not append
offline_access to the authorization request.
The connector should either:
- rely on the user-provided refresh_token scope, or
- append refresh_token when refresh-token support is enabled and the scope does
not already include it, or - otherwise avoid adding an unsupported scope when the OAuth server is Snowflake
custom OAuth.
Why this looks like a connector issue
Snowflake custom OAuth docs list these relevant valid authorization scopes:
- refresh_token
- session:role:
- session:role-encoded:<URL_ENCODED_ROLE>
The docs describe refresh_token as the scope that requests offline access:
https://docs.snowflake.com/en/user-guide/oauth-custom
But current connector code appends offline_access whenever refresh-token support
is enabled:
if refresh_token_enabled:
self._scope += (" " if self._scope else "") + "offline_access"
In my local install this is in:
snowflake/connector/auth/_oauth_base.py
Impact
This prevents using Snowflake CLI / Python connector authorization-code OAuth with
Snowflake custom OAuth and refresh-token caching.
A minimal OAUTH_AUTHORIZATION_CODE config without refresh-token settings works,
but it opens the browser every time. Enabling refresh-token reuse causes the
invalid scope error before authentication.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.