Skip to content

docs: Per-user OIDC tokens for identity pass-through - #12051

Open
keydunov wants to merge 1 commit into
masterfrom
claude/gallant-ramanujan-5un5s0
Open

keydunov wants to merge 1 commit into
masterfrom
claude/gallant-ramanujan-5un5s0

Conversation

@keydunov

Copy link
Copy Markdown
Member

Documents the new User token subject for OIDC token configs (cubejs-enterprise #15630): per-user tokens delivered in securityContext.cubeCloud.oidcTokens, user placeholders for sub and 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

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018FaGRKzo5UinU2ZG3QYm4C
@mintlify

mintlify Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
cubed3 🟢 Ready View Preview Sep 30, 2026, 12:09 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

@github-actions github-actions Bot added the docs Issues that require a documentation improvement label Sep 30, 2026
@claude

claude Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

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
  • Read diff and the full page
  • Checked the sample against SnowflakeDriver and server-core driver caching
  • Resolved/checked prior threads
  • Posted review

Findings

Severity Where Issue
High docs-mintlify/admin/deployment/oidc/index.mdx:237 SnowflakeDriver has no token option; it reads oauthToken (packages/cubejs-snowflake-driver/src/SnowflakeDriver.ts:424). The user's token is dropped, and the driver falls back to a token file. That can be the deployment's token.
High docs-mintlify/admin/deployment/oidc/index.mdx:239 No contextToOrchestratorId. Drivers are cached per orchestrator, and the default id is 'STANDALONE' (server.ts:247, :664-668), so the first user's token serves every user. oauth-authentication.mdx:232-261 already documents this pattern.
Medium docs-mintlify/admin/deployment/oidc/index.mdx:231 securityContext.cubeCloud.oidcTokens throws when cubeCloud is undefined. The refresh worker and pre-aggregation builds have no user, so this data source can never build pre-aggregations. The doc needs a fallback or a sentence saying so.
Low docs-mintlify/admin/deployment/oidc/index.mdx:235 SnowflakeDriver is used without a require. Returning { type: "snowflake", ... } avoids the import, as the sibling page does.
Low docs-mintlify/admin/deployment/oidc/index.mdx:104 The fields table has no Token subject row. I couldn't post this inline because line 104 is outside the diff. Suggested row: | **Token subject** | \Deployment` (default) or `User` (preview) — see Per-user tokens below. |`

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 <Warning> follows the docs-mintlify/CLAUDE.md convention and doesn't expose the flag name.

Review threads

The 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,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Suggested change
token: oidc.token,
oauthToken: oidc.token,

Comment on lines +239 to +240
},
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Suggested change
},
};
},
// 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.

Comment on lines +231 to +234
const oidc = securityContext.cubeCloud.oidcTokens?.snowflake_user;
if (oidc?.status !== "active") {
throw new Error(oidc?.error ?? "No user token available");
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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:

Suggested change
return new SnowflakeDriver({
return {
type: "snowflake",

(Then close with }; instead of });.)

This branch was successfully deployed

1 active deployment
staging - docs-mintlify — f2f8255a Deployed Sep 30, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Issues that require a documentation improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants