Skip to content

Switch SiS demo to OAuth session token auth#63

Draft
j-seuren wants to merge 5 commits intoJetBrains:mainfrom
j-seuren:j-seuren/sis-oauth-session-token-auth
Draft

Switch SiS demo to OAuth session token auth#63
j-seuren wants to merge 5 commits intoJetBrains:mainfrom
j-seuren:j-seuren/sis-oauth-session-token-auth

Conversation

@j-seuren
Copy link

Summary

Switch the Snowflake demo from password-based service user auth to OAuth session token auth in Streamlit-in-Snowflake. The app now authenticates as the logged-in user by reading the SPCS-provided token from /snowflake/session/token, eliminating stored credentials.

Draft: Pending end-to-end validation in a SiS deployment before merging.

Changes

OAuth session token authentication

Monkey-patches SnowflakeIntrospector._connect when running in SiS to use authenticator=oauth with a fresh token on every connection (avoids ~1h expiry).

Files
  • examples/demo-snowflake-project/src/databao_snowflake_demo/app.py
  • examples/demo-snowflake-project/databao/domains/root/src/snowflake.yaml

Remove service user infrastructure

Drops the service user, network policy, and user/password/account secrets from setup/cleanup SQL.

Files
  • examples/demo-snowflake-project/setup.sql
  • examples/demo-snowflake-project/cleanup.sql

Documentation update

Updates README to reflect the new auth model and note that users need USAGE grants.

Files
  • examples/demo-snowflake-project/README.md

Test Plan

  • uv run ruff check passes
  • uv run pytest tests/ -v — 65/65 pass
  • Deploy to SiS and verify OAuth token auth works end-to-end

🤖 Generated with Claude Code

j-seuren and others added 3 commits March 19, 2026 15:54
Replace password-based service user authentication with OAuth session token auth in the Streamlit-in-Snowflake demo. The app now reads the SPCS-provided token from /snowflake/session/token on every connection, authenticating as the logged-in Snowflake user. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The YAML now includes `authenticator: externalbrowser` so local dev works out of the box with Snowflake SSO. In SiS, the monkey-patch overrides this with OAuth token auth. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Switches the Streamlit-in-Snowflake (SiS) demo from stored Snowflake service-user credentials to using the SiS-provided OAuth session token so the app authenticates as the logged-in Snowflake user.

Changes:

  • Monkey-patches SnowflakeIntrospector._connect in SiS to connect with authenticator=oauth + fresh token read from /snowflake/session/token.
  • Removes service-user / network-policy setup and deletes datasource credential secrets from setup/cleanup SQL.
  • Updates demo Snowflake domain config and README to reflect new auth model and required grants.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
examples/demo-snowflake-project/src/databao_snowflake_demo/app.py Adds SiS detection + token-based OAuth connect patch for the Snowflake introspector.
examples/demo-snowflake-project/setup.sql Removes service-user/network-policy provisioning and datasource credential secrets; keeps only warehouse/database config secrets.
examples/demo-snowflake-project/cleanup.sql Removes cleanup steps for the deleted service-user/network-policy resources.
examples/demo-snowflake-project/databao/domains/root/src/snowflake.yaml Switches account env var to SNOWFLAKE_ACCOUNT and uses externalbrowser auth for local runs (overridden in SiS by the patch).
examples/demo-snowflake-project/README.md Updates documentation for token auth, new env vars, and required USAGE grants.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +113 to +114
SnowflakeIntrospector._connect = _sis_connect # type: ignore[assignment]
logger.info("Patched SnowflakeIntrospector._connect for SiS OAuth token auth")
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overwriting SnowflakeIntrospector._connect at the class level is a broad monkey-patch (affects all instances in-process) and Streamlit reruns can re-apply it repeatedly. Consider adding an idempotency guard (e.g., a sentinel attribute) and/or preserving the original method so it can be restored if needed (helps avoid surprising behavior in mixed environments/tests).

Copilot uses AI. Check for mistakes.
"""
@contextmanager
def _sis_connect(self: Any, file_config: Any, *, catalog: str | None = None) -> Generator[Any, None, None]:
token = SESSION_TOKEN_PATH.read_text().strip()
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SESSION_TOKEN_PATH.read_text().strip() can raise (e.g., transient file-not-found/permission issues) and can also produce an empty token; either case will currently bubble up as a low-level exception or a confusing connector auth failure. Consider catching OSError/decode errors, validating the token is non-empty, and raising/logging a clear message that the SiS OAuth session token could not be read from /snowflake/session/token.

Suggested change
token = SESSION_TOKEN_PATH.read_text().strip()
try:
raw_token = SESSION_TOKEN_PATH.read_text()
except (OSError, UnicodeDecodeError) as exc:
msg = (
f"Failed to read SiS OAuth session token from {SESSION_TOKEN_PATH!s}. "
"Ensure the token file exists and is readable inside Snowflake."
)
logger.error(msg, exc_info=True)
raise RuntimeError(msg) from exc
token = raw_token.strip()
if not token:
msg = (
f"SiS OAuth session token file {SESSION_TOKEN_PATH!s} is empty. "
"Connector authentication cannot proceed."
)
logger.error(msg)
raise RuntimeError(msg)
Copilot uses AI. Check for mistakes.
Comment on lines +94 to +95
snowflake.connector.paramstyle = "qmark"
kwargs = file_config.connection.to_snowflake_kwargs()
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting snowflake.connector.paramstyle = "qmark" mutates connector global state for the whole process (including any other Snowflake connections Streamlit may open). If this is only needed for the introspector connection, consider limiting the scope (set/restore around the connect) or moving it to a one-time initialization with a clear comment explaining why the global change is safe here.

Copilot uses AI. Check for mistakes.
j-seuren and others added 2 commits March 25, 2026 10:43
Instead of pre-filling the password field with the env var value (which gets sent to the browser), show a disabled field with a placeholder indicating the env var is in use. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The agent executes SQL through DuckDB's Snowflake extension (separate from the introspector path). The default adapter doesn't support OAuth token auth, so we monkey-patch _create_secret_sql and _create_connection_string to inject the SPCS session token. Also adds the SNOWFLAKE_HOST parameter to both patches — Snowflake docs state the SPCS token can only be used with the SPCS-provided host endpoint. Corrects README claims about owner's rights vs caller's rights. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants