Create a Snowflake Data Source
Follow these steps to connect to Snowflake and create a Snowflake data source:
- Configure User Access Rights.
- Review the available Snowflake Authentication Options.
- If you use External OAuth, configure Okta and Snowflake.
- Create a Snowflake Data Source.
Refer to Additional Information for performance tips, limitations, and information about Snowflake feature support.
Configure User Access Rights
The required Snowflake user configuration depends on the authentication method.
Key Pair and Basic Authentication
We recommend creating a dedicated user and user role specifically for integrating with GoodData.
Steps:
Create a user role and grant it the following access rights:
GRANT USAGE ON WAREHOUSE {warehouse_name} TO ROLE {role_name}; GRANT USAGE ON DATABASE {database_name} TO ROLE {role_name}; GRANT USAGE ON SCHEMA {database_name}.{schema_name} TO ROLE {role_name}; GRANT SELECT ON ALL TABLES IN SCHEMA {database_name}.{schema_name} TO ROLE {role_name}; GRANT SELECT ON FUTURE TABLES IN SCHEMA {database_name}.{schema_name} TO ROLE {role_name}; GRANT SELECT ON ALL VIEWS IN SCHEMA {database_name}.{schema_name} TO ROLE {role_name}; GRANT SELECT ON FUTURE VIEWS IN SCHEMA {database_name}.{schema_name} TO ROLE {role_name};Create a user and assign them the user role:
GRANT ROLE {role_name} TO USER {user_name};Make the user role default for the user:
ALTER USER {user_name} SET DEFAULT_ROLE={role_name};
External OAuth
External OAuth propagates the signed-in user’s identity to Snowflake. Each user must therefore have a corresponding Snowflake user.
For every user who will access the data source:
- Set the Snowflake
LOGIN_NAMEto the value provided in the Okta access token’ssubclaim. This is commonly the user’s email address or login. - Assign a default Snowflake role. Snowflake does not allow
ACCOUNTADMIN,SECURITYADMIN, orORGADMINas the default role for External OAuth connections. - Grant the role
USAGEon the warehouse, database, and schema, andSELECTon the required tables and views. - Review
DEFAULT_SECONDARY_ROLES. Secondary roles can grant access to additional data beyond the default role.
Snowflake Authentication Options
Snowflake supports the following authentication options:
- Key Pair Authentication (Recommended for shared credentials): Requires a private key and an optional encryption passphrase.
- Basic Authentication: Requires a username and password. Snowflake is deprecating this method.
- External OAuth (Beta): Propagates the signed-in user’s Okta access token to Snowflake. Snowflake then applies the permissions and row-level security configured for that user.
Beta Feature
External OAuth for Snowflake is a beta feature available in GoodData.CN. It currently supports Okta as the OIDC provider.
External OAuth must be explicitly selected for the data source. Keep data result caching disabled for data sources that use External OAuth. Cached results could otherwise be shared between users with different Snowflake permissions.
Snowflake is deprecating password-based Basic Authentication. Use Key Pair authentication for shared-credential data sources.
When using Key Pair authentication, enter the private key exactly as generated, including the prefix (-----BEGIN PRIVATE KEY-----), suffix (-----END PRIVATE KEY-----), and line breaks.
For instructions on generating private keys, see Snowflake’s documentation.
Configure External OAuth with Okta
External OAuth uses the user’s interactive Okta session for both GoodData sign-in and Snowflake authentication. Okta issues an identity token for GoodData and an access token that GoodData forwards to Snowflake.
Before configuring the data source, configure Okta, Snowflake, and the GoodData identity provider.
Create an Okta Authorization Server
In Okta Admin, go to Security > API > Authorization Servers.
Create a custom authorization server.
Set its audience to your Snowflake account URL in this format:
https://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.comSave the authorization server and note its issuer URL. It has the following format:
https://<OKTA_DOMAIN>/oauth2/<AUTHORIZATION_SERVER_ID>
Do not use Okta’s built-in default authorization server. It cannot provide the required Snowflake audience and role scope.
Add the Snowflake Role Scope
On the authorization server, add one of the following scopes:
session:role-anyto allow users to connect with any Snowflake role assigned to them.session:role:<ROLE_NAME>to allow a specific role only.
Confirm the User Claims
Confirm that the tokens contain identifiers that can be matched to GoodData and Snowflake users:
- The access token’s
subclaim must match the Snowflake user’sLOGIN_NAME. - The ID token must include
preferred_username. GoodData uses this claim to identify the user. Request the Oktaprofilescope to include it.
Create the Okta Application
Create an OIDC web application with the following settings:
- Grant type: Authorization Code
- Client authentication: Client secret
- Require PKCE as additional verification: Disabled
- Sign-in redirect URI:
https://<GOODDATA_HOST>/login/oauth2/code/<IDENTITY_PROVIDER_ID> - Sign-out redirect URI:
https://<GOODDATA_HOST>/logout - Scopes:
openid,profile,offline_access, and the Snowflake role scope
Assign the application to the users or groups who will use External OAuth. Each user must also exist in GoodData and Snowflake.
Create the Snowflake Security Integration
Create an External OAuth security integration in Snowflake:
CREATE SECURITY INTEGRATION external_oauth_okta
TYPE = external_oauth
ENABLED = true
EXTERNAL_OAUTH_TYPE = okta
EXTERNAL_OAUTH_ISSUER = 'https://<OKTA_DOMAIN>/oauth2/<AUTHORIZATION_SERVER_ID>'
EXTERNAL_OAUTH_JWS_KEYS_URL = 'https://<OKTA_DOMAIN>/oauth2/<AUTHORIZATION_SERVER_ID>/v1/keys'
EXTERNAL_OAUTH_AUDIENCE_LIST = ('https://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com')
EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM = 'sub'
EXTERNAL_OAUTH_SNOWFLAKE_USER_MAPPING_ATTRIBUTE = 'login_name'
EXTERNAL_OAUTH_ANY_ROLE_MODE = 'ENABLE';The issuer, JWS keys URL, and audience must match the Okta authorization server and Snowflake account URL exactly. EXTERNAL_OAUTH_ANY_ROLE_MODE = 'ENABLE' is required when you use the session:role-any scope.
Register the Identity Provider in GoodData
Create the identity provider:
curl "$HOST_URL/api/v1/entities/identityProviders" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/vnd.gooddata.api+json" \
-X POST \
-d '{
"data": {
"type": "identityProvider",
"id": "<IDENTITY_PROVIDER_ID>",
"attributes": {
"identifiers": ["<GOODDATA_HOST>"],
"oauthIssuerLocation": "https://<OKTA_DOMAIN>/oauth2/<AUTHORIZATION_SERVER_ID>",
"oauthClientId": "<OKTA_CLIENT_ID>",
"oauthClientSecret": "<OKTA_CLIENT_SECRET>",
"oauthCustomScopes": ["session:role-any"],
"oauthSubjectIdClaim": "preferred_username",
"idpType": "CUSTOM_IDP"
}
}
}'The identity provider ID must match the ID used in the Okta sign-in redirect URI.
Activate the identity provider:
curl "$HOST_URL/api/v1/actions/organization/switchActiveIdentityProvider" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-X POST \
-d '{ "idpId": "<IDENTITY_PROVIDER_ID>" }'The identity provider change may take a few minutes to become active.
Create a Snowflake Data Source
Once you have configured your Snowflake user’s access rights, you can proceed to create a Snowflake data source that you can then connect to.
On the home page switch to Data sources.
Click Connect data.
Select Snowflake.
Name your data source and select an authentication method:
- For Key Pair, enter the username, private key, and optional passphrase.
- For Basic, enter the username and password.
- For External OAuth, enter the account name, database, and warehouse. Do not enter Snowflake credentials. The signed-in user’s Okta access token is used for the connection.
Click Connect.
Input your schema name and click Save:
Your data source is created!
Create a Snowflake data source using Key Pair authentication with the following API call:
curl $HOST_URL/api/v1/entities/dataSources \ -H "Content-Type: application/vnd.gooddata.api+json" \ -H "Accept: application/vnd.gooddata.api+json" \ -H "Authorization: Bearer $API_TOKEN" \ -X POST \ -d '{ "data": { "type": "dataSource", "id": "<unique_id_for_the_data_source>", "attributes": { "name": "<data_source_display_name>", "url": "jdbc:snowflake://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com:5432?warehouse=<SNOWFLAKE_WAREHOUSE>&db=<SNOWFLAKE_DBNAME>", "schema": "<SNOWFLAKE_SCHEMA>", "type": "SNOWFLAKE", "username": "<SNOWFLAKE_USER>", "privateKey": "<SNOWFLAKE_PRIVATEKEY>", "privateKeyPassphrase": "<SNOWFLAKE_PRIVATEKEY_PASSPHRASE>" # This parameter is optional. } } }' | jq .To create a Snowflake data source that uses External OAuth, omit shared authentication properties and disable caching:
curl $HOST_URL/api/v1/entities/dataSources \ -H "Content-Type: application/vnd.gooddata.api+json" \ -H "Accept: application/vnd.gooddata.api+json" \ -H "Authorization: Bearer $API_TOKEN" \ -X POST \ -d '{ "data": { "type": "dataSource", "id": "<DATA_SOURCE_ID>", "attributes": { "name": "<DATA_SOURCE_NAME>", "url": "jdbc:snowflake://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com?warehouse=<SNOWFLAKE_WAREHOUSE>&db=<SNOWFLAKE_DATABASE>", "schema": "<SNOWFLAKE_SCHEMA>", "type": "SNOWFLAKE", "cacheStrategy": "NEVER" } } }'If you add a username, password, token, or private key to the data source, those credentials take precedence and the signed-in user’s Okta token is not used.
Alternatively, you can still create a Snowflake data source using Basic Authentication (deprecated by Snowflake) with the following API call:
curl $HOST_URL/api/v1/entities/dataSources \ -H "Content-Type: application/vnd.gooddata.api+json" \ -H "Accept: application/vnd.gooddata.api+json" \ -H "Authorization: Bearer $API_TOKEN" \ -X POST \ -d '{ "data": { "type": "dataSource", "id": "<unique_id_for_the_data_source>", "attributes": { "name": "<data_source_display_name>", "url": "jdbc:snowflake://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com:5432?warehouse=<SNOWFLAKE_WAREHOUSE>&db=<SNOWFLAKE_DBNAME>", "schema": "<SNOWFLAKE_SCHEMA>", "type": "SNOWFLAKE", "username": "<SNOWFLAKE_USER>", "password": "<SNOWFLAKE_PASSWORD>" } } }' | jq .See the API reference guide for further details.
To confirm that the data source has been created, ensure the server returns the following response:
{ "data": { "type": "dataSource", "id": "<unique_id_for_the_data_source>", "attributes": { "authenticationType": "<type-of-authentication>", "name": "<data_source_display_name>", "url": "jdbc:snowflake://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com:5432?warehouse=<SNOWFLAKE_WAREHOUSE>&db=<SNOWFLAKE_DBNAME>", "schema": "<SNOWFLAKE_SCHEMA>", "type": "SNOWFLAKE", "username": "<SNOWFLAKE_USER>" } }, "links": { "self": "$HOST_URL/api/v1/entities/dataSources/<unique_id_for_the_data_source>" } }
Create a Snowflake data source using Key Pair authentication with the following example:
from gooddata_sdk import GoodDataSdk, CatalogWorkspace, BasicCredentials, CatalogDataSourceSnowflake, SnowflakeAttributes
host = "<GOODDATA_URI>"
token = "<API_TOKEN>"
sdk = GoodDataSdk.create(host, token)
sdk.catalog_data_source.create_or_update_data_source(
CatalogDataSourceSnowflake(
id=data_source_id,
name=data_source_name,
db_specific_attributes=SnowflakeAttributes(
account=os.environ["SNOWFLAKE_ACCOUNT"],
warehouse=os.environ["SNOWFLAKE_WAREHOUSE"],
db_name=os.environ["SNOWFLAKE_DBNAME"]
),
schema=os.environ["SNOWFLAKE_SCHEMA"],
credentials=BasicCredentials(
username=os.environ["SNOWFLAKE_USER"],
privateKey=os.environ["SNOWFLAKE_PRIVATEKEY"],
privateKeyPassphrase=os.environ["SNOWFLAKE_PRIVATEKEY_PASSPHRASE"], # This parameter is optional.
),
)
)Alternatively, create a Snowflake data source using basic authentication with the following API call:
from gooddata_sdk import GoodDataSdk, CatalogWorkspace, BasicCredentials, CatalogDataSourceSnowflake, SnowflakeAttributes
host = "<GOODDATA_URI>"
token = "<API_TOKEN>"
sdk = GoodDataSdk.create(host, token)
sdk.catalog_data_source.create_or_update_data_source(
CatalogDataSourceSnowflake(
id=data_source_id,
name=data_source_name,
db_specific_attributes=SnowflakeAttributes(
account=os.environ["SNOWFLAKE_ACCOUNT"],
warehouse=os.environ["SNOWFLAKE_WAREHOUSE"],
db_name=os.environ["SNOWFLAKE_DBNAME"]
),
schema=os.environ["SNOWFLAKE_SCHEMA"],
credentials=BasicCredentials(
username=os.environ["SNOWFLAKE_USER"],
password=os.environ["SNOWFLAKE_PASSWORD"],
),
)
)Additional Information
External OAuth Limitations
The following limitations apply during the beta:
- Okta is the only supported OIDC provider.
- External OAuth works only for interactive browser sessions in which the user signed in through Okta.
- Queries executed with a static GoodData API token do not have a user Okta token to forward to Snowflake.
- Scheduled exports and alerts are not supported because they run without an interactive user session.
- Data result caching must remain disabled for the data source.
- If shared Snowflake credentials are configured on the data source, GoodData uses those credentials instead of External OAuth.
External OAuth Troubleshooting
GoodData opens its built-in sign-in page instead of Okta
Make sure the Okta identity provider is active for the organization. After switching the active identity provider, allow a few minutes for the change to take effect.
Okta reports an invalid redirect URI
Make sure the redirect URI in the Okta application exactly matches:
https://<GOODDATA_HOST>/login/oauth2/code/<IDENTITY_PROVIDER_ID>GoodData reports that the authenticated user cannot be found
Set oauthSubjectIdClaim to preferred_username and make sure the GoodData user’s authentication ID matches that claim.
A query fails with Missing user name
Make sure you are testing through an interactive browser session. A static API token does not contain the user’s Okta token. Also confirm that the data source does not contain shared Snowflake credentials.
Snowflake reports that no default role is assigned
Assign a non-administrative default role to the Snowflake user.
Snowflake rejects the requested role
If you use session:role-any, set EXTERNAL_OAUTH_ANY_ROLE_MODE to ENABLE in the Snowflake security integration.
The user can access more data than expected
Review the user’s DEFAULT_SECONDARY_ROLES in Snowflake. Secondary roles can grant additional access beyond the default role.
Scheduled exports or alerts do not run
This is a current limitation. These operations do not have an interactive user’s Okta token to forward to Snowflake.
Query Tagging
GoodData can attach query tags to SQL statements so you can trace database workload back to its origin in GoodData. Tags are added automatically to supported executions when query tagging is enabled.
Query tagging is supported for:
- Visualization queries
- Label elements queries (for example, loading attribute values in filters)
Query tagging is not applied to exports (PDF, XLSX, CSV), alerts, or scheduled exports.
What Gets Tagged
Tags include execution context such as:
- Organization ID
- Workspace ID
- User ID
- Execution type (visualization query vs label elements query)
- When available, identifiers of the triggering dashboard and visualization
This metadata is intended for observability and performance troubleshooting. It does not include raw data values.
Enable Query Tagging
Query tagging is controlled by the ENABLE_QUERY_TAGS setting. You can enable it at the workspace level or at the organization level. The setting value is a boolean (true or false).
Example
Enabling query tagging at the workspace level:
curl -H "Authorization: Bearer ${API_KEY}" \
-X POST \
-H "Content-Type: application/vnd.gooddata.api+json" \
-H "Accept: application/vnd.gooddata.api+json" \
-d '{
"data": {
"type": "workspaceSetting",
"id": "enable_query_tags",
"attributes": {
"content": { "value": true },
"type": "ENABLE_QUERY_TAGS"
}
}
}' \
"https://${HOSTNAME}/api/v1/entities/workspaces/${WORKSPACE_ID}/workspaceSettings"Snowflake Notes
Snowflake supports native query tagging. GoodData sets a JSON tag using ALTER SESSION SET QUERY_TAG for the duration of the query and clears it afterwards. You can see the tag in Snowflake query history and monitoring tools that surface the QUERY_TAG field.
Data Source Details
The JDBC URL must be in the following format:
jdbc:snowflake://<db_account>.snowflakecomputing.com:<db_port>?warehouse=<db_warehouse>&db=<db_name>Key Pair authentication does not change the JDBC URL. Provide the username and private key in the credentials fields when creating or editing the data source.
GoodData uses up-to-date drivers.
Performance Tips
If your database holds a large amount of data, consider the following practices:
- GoodData’s connection pool allows for up to 24 connections. Snowflake’s default setting permits only 8 connections. We recommend increasing your Snowflake’s connection pool size to 24.
- Denormalize the relational data model of your database. This helps avoid large JOIN operations. Because Snowflake is a columnar database, queries read only the required columns and each column is compressed separately.
- Spin up databases/instances based on user needs.
- Users with similar needs populate data into caches that are likely reused.
- Isolate data transformation operations running in your database from the analytics generated by GoodData.
- Set up proper auto-scaling based on users needs.
- Utilize materialized views
- Changes to underlying tables are propagated to related materialized views, they are always consistent
- Materialize results of JOINs / aggregations which are executed very often as a result of execution of dashboards / visualizations from GoodData
- Map materialized views and their columns to datasets and LDM and utilize them in metrics / visualizations / dashboards
Query Timeout
The default timeout value for queries is 160 seconds. If a query takes longer than 160 seconds, it is stopped. The user then receives a status code 400 and the message Query timeout occurred.
Query timeout is closely related to the ACK timeout. For proper system configuration, the ACK timeout should be longer than the query timeout. The default ACK timeout value is 170 seconds.
Supported URL Parameters
These are advanced JDBC driver properties. In most cases, GoodData UI does not expose or validate them, so use them with caution.
Snowflake data sources do not support the separate data.attributes.parameters attribute. Append supported properties directly to the JDBC URL in data.attributes.url instead. A parameter being listed here means the JDBC driver accepts it, but it does not guarantee that the related capability is fully supported by GoodData and some values may still cause unexpected errors. Some authentication-related parameters may be accepted by the JDBC driver, even if GoodData may not fully support it.
Example
"attributes": {
"name": "<data_source_display_name>",
"url": "jdbc:snowflake://<SNOWFLAKE_ACCOUNT>.snowflakecomputing.com:5432?warehouse=<SNOWFLAKE_WAREHOUSE>&db=<SNOWFLAKE_DBNAME>&role=<SNOWFLAKE_ROLE>&queryTimeout=30",
"schema": "<SNOWFLAKE_SCHEMA>",
"type": "SNOWFLAKE",
"username": "<SNOWFLAKE_USER>",
"password": "<SNOWFLAKE_PASSWORD>"
}The supported URL parameters for Snowflake data sources are:
- db
- loginTimeout
- networkTimeout
- ocspFailOpen
- passcode
- passcodeInPassword
- useProxy
- proxyHost
- proxyPort
- proxyUser
- proxyPassword
- proxyProtocol
- queryTimeout
- role
- stringsQuotedForColumnDef
- token
- warehouse





