Skip to main content
This feature is in beta. Reach out to your account manager to have it enabled for your Cube deployment.

Use case

You want each user’s queries to run under their own database identity using OAuth tokens managed by Cube. When a user has no active token, for example because they haven’t authorized yet, Cube falls back to a service account, which also runs background operations such as pre-aggregation builds. This pattern applies to any data source that supports OAuth, including Databricks and Snowflake. The examples below use Databricks; for any other OAuth-capable data source, update the driver options. Because every user connects with different credentials, you also need per-user query orchestrator state. Without this, one user’s cached connection could leak to another.

Prerequisites

  • A Cube deployment connected to an OAuth-capable data source
  • OAuth configured in your data source so that Cube can obtain per-user tokens (via the User Credentials feature)
  • A service account credential (token or password) stored as an environment variable, used for background operations and for users without an active token
The service account credential is used for background operations, such as pre-aggregation builds, and for queries from users without an active token, who see whatever the service account can access. Grant it the minimum permissions necessary — ideally read-only access to the required schemas — to limit exposure. To reject those queries instead, make driver_factory fail closed for user requests and keep the service account token only for the refresh worker’s context, as in the per-user OIDC token example. Fail closed with a non-empty token the warehouse rejects: an empty token makes the Databricks and Snowflake drivers read a credential from the environment instead.Anyone who can sign tokens with the deployment’s API secret can set cubeCloud.username and query as that user, with that user’s OAuth token. Protect the API secret like your users’ credentials.

Set up the OAuth app

Before configuring Cube to use per-user OAuth, register your data source as an OAuth app in Cube:
1

Open the OAuth apps settings

In Cube, go to Admin → Integrations → OAuth apps and click Create OAuth app.
Admin Integrations page showing the OAuth apps section with the Create OAuth app button
2

Fill out the OAuth app details

Provide the OAuth app metadata from your data source: Name, Auth URL, Token URL, Client ID, Client secret, and any required Scopes. Copy the Redirect URI shown in this form and register it with your data source’s OAuth provider, then click Create.Request a refresh token so users don’t have to authorize again each time the access token expires. For Databricks, add offline_access to Scopes and to the Databricks OAuth app, and set token_access_policy.refresh_token_ttl_in_minutes on the Databricks OAuth app to how long a user can go before authorizing again.
New OAuth app form with fields for Name, Auth URL, Token URL, Client ID, Client Secret, Scopes, and Redirect URI
3

Authorize the app

Each user does this for their own account. An admin’s token is never used for other users.Open the sidebar and go to Connected apps. Find your OAuth app and click Authorize to generate an access token.Cube refreshes the access token automatically as long as the provider issues a refresh token. A user needs to authorize again only if the refresh token expires or is revoked; Connected apps shows the current status.
Connected apps page showing the OAuth integration with an Authorize action

Configuration

The configuration uses two options from the configuration file reference:
  • driver_factory — dynamically selects the authentication credential per request
  • context_to_orchestrator_id — gives each user, and each of their tokens, a separate query orchestrator instance (database connections, execution queues, pre-aggregation table caches)

Environment variables

Set the environment variables for your data source. The examples below show Databricks and Snowflake; adapt them to your specific setup.
Use a token for the service account. If CUBEJS_DB_DATABRICKS_OAUTH_CLIENT_ID is set, the driver authenticates as that service principal and ignores the per-user token.

Configuration file

The examples below use Databricks with an OAuth app named databricks. userCredentials is keyed by the Name of the OAuth app, so replace databricks with the name of your app. To target a different data source, also update the driver_factory return value with the correct type and driver-specific options. See the data sources reference for available drivers.
cube.py

How it works

  1. User makes a request — Cube attaches the user’s own OAuth credentials to securityContext.cubeCloud.userCredentials.<app_name>, where <app_name> is the Name of the OAuth app, as { status, accessToken, accessTokenExpiresAt, issuedAt }. issuedAt changes whenever the token is replaced. Requests that aren’t tied to a Cube user carry no user credentials, so they also fall back to the service account. This includes requests authenticated with your own JWT or checkAuth, unless their security context sets cubeCloud.username.
  2. driver_factory resolves the credential — If the credential status is active, the user’s OAuth token is used. Otherwise — the user hasn’t authorized (missing), or the token is expired or in error — Cube falls back to the service account credential stored in environment variables.
  3. Per-user orchestrator — context_to_orchestrator_id returns a unique key per username, so each user gets their own database connection pool, execution queues, and pre-aggregation table cache. Without this, Cube would share a single cached connection across all users, causing one user’s credentials to be reused for another user’s queries. Cube builds the driver once per orchestrator, so the key also includes the token’s issuedAt: when a user authorizes or their token is refreshed, Cube builds a new connection with the current token. The trade-off: each refresh starts the user on a new orchestrator with an empty cache and new connections, and superseded orchestrators keep theirs, which the liveness probe keeps testing, until they are evicted from the orchestrator cache.