Conversation
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018FaGRKzo5UinU2ZG3QYm4C
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
|
Claude finished @keydunov's task in 1m 34s —— View job Changes requested: the per-user code sample doesn't work as written. 2 high, 1 medium, 2 low. Review details
Findings
Open question: tokens have a 1h TTL, but a per-user orchestrator keeps its driver for as long as the orchestrator lives. Please confirm whether Cube Cloud rebuilds the driver when the token refreshes. If it doesn't, the doc should say how token expiry is handled. The preview Review threadsThe listing returned 0 of my own threads (no prior threads), so there was nothing to resolve or re-affirm. |
| } | ||
| return new SnowflakeDriver({ | ||
| authenticator: "OAUTH", | ||
| token: oidc.token, |
There was a problem hiding this comment.
High: SnowflakeDriver ignores token. With authenticator: "OAUTH" it reads oauthToken, and when that's empty it falls back to a token file (packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts:424):
config.token = this.config.oauthToken || await this.readOAuthToken();As written, the user's token is dropped. The driver then reads CUBEJS_DB_SNOWFLAKE_OAUTH_TOKEN_PATH or /snowflake/session/token. That either fails with File ... does not exist, or it quietly connects with the deployment's token when a deployment-subject Snowflake config sets that env var. The second case is exactly the per-user isolation this section promises.
| token: oidc.token, | |
| oauthToken: oidc.token, |
| }, | ||
| }; |
There was a problem hiding this comment.
High: the sample has no contextToOrchestratorId, so the first user's token ends up serving every user. Drivers are cached once per orchestrator (packages/cubejs-server-core/src/core/server.ts:664-668), and the default orchestrator id is the constant 'STANDALONE' (server.ts:247). That means driverFactory runs once per data source, and every later request reuses the driver built with the first user's token. Snowflake then applies that user's role to everyone.
The sibling page already covers this (admin/connect-to-data/oauth-authentication.mdx:232-237, with the explanation at :255-261). Keying the orchestrator per user also keeps each user's query cache separate.
| }, | |
| }; | |
| }, | |
| // One orchestrator (driver, queues, cache) per user — otherwise the first | |
| // user's driver and token are reused for every request. | |
| contextToOrchestratorId: ({ securityContext }) => | |
| `CUBE_APP_${securityContext?.cubeCloud?.username ?? "default"}`, | |
| }; |
This also bears on the 1h token TTL. A per-user orchestrator keeps its driver for as long as the orchestrator lives, so it's worth confirming whether Cube Cloud rebuilds the driver when the token refreshes, or whether the doc needs to say how expiry is handled.
| const oidc = securityContext.cubeCloud.oidcTokens?.snowflake_user; | ||
| if (oidc?.status !== "active") { | ||
| throw new Error(oidc?.error ?? "No user token available"); | ||
| } |
There was a problem hiding this comment.
Medium: driverFactory also runs without a signed-in user, and the sample breaks there: the refresh worker, scheduled pre-aggregation builds and schema introspection all call it. In those contexts securityContext.cubeCloud can be undefined, and securityContext.cubeCloud.oidcTokens?.… throws TypeError: Cannot read properties of undefined. Where cubeCloud is set but has no user token, the sample throws on purpose, so pre-aggregations on this data source can never build.
Use securityContext?.cubeCloud?.oidcTokens?.snowflake_user. Then either fall back to a deployment-subject connection when there's no user, as oauth-authentication.mdx:215-226 does, or add a sentence saying pre-aggregations and refresh aren't supported on a per-user-only data source.
| if (oidc?.status !== "active") { | ||
| throw new Error(oidc?.error ?? "No user token available"); | ||
| } | ||
| return new SnowflakeDriver({ |
There was a problem hiding this comment.
Low: SnowflakeDriver is used without being required, so pasting the sample gives ReferenceError: SnowflakeDriver is not defined. The sibling page returns a config object instead (oauth-authentication.mdx:222), which needs no import:
| return new SnowflakeDriver({ | |
| return { | |
| type: "snowflake", |
(Then close with }; instead of });.)
Documents the new
Usertoken subject for OIDC token configs (cubejs-enterprise #15630): per-user tokens delivered insecurityContext.cubeCloud.oidcTokens, user placeholders forsuband claim values, and the error-entry behavior. Marked as preview (gated by a tenant flag).Added as a "Per-user tokens" section on
admin/deployment/oidc/index.mdx.🤖 Generated with Claude Code
https://claude.ai/code/session_018FaGRKzo5UinU2ZG3QYm4C
Generated by Claude Code