# Snowflake {: #snowflake }

## Supported authentication {: #supported-authentication }

- [Username/password](#username-password)
- [Snowflake OAuth](#snowflake-oauth)
- [External OAuth](#snowflake-external-oauth) with Okta or AzureAD

## Username/password {: #username-password}

### Prerequisites {: #prerequisites }

The following is required before connecting to Snowflake in DataRobot:

* A Snowflake account

!!! warning "OAuth with security integrations"
  	If you create a security integration when configuring OAuth, you must specify the `OAUTH_REDIRECT_URI` as `https://<datarobot_app_server>/account/snowflake/snowflake_authz_return`.

### Required parameters {: #required-parameters }

In addition to the required fields listed below, you can learn about other available configuration options in the [Snowflake documentation](https://docs.snowflake.com/en/user-guide/jdbc-parameters.html).

Required field | Description | Documentation
--------------- | ---------- | -----------
`address`       | A connection object that stores a secure connection URL to connect to Snowflake.<br><br>**Example:** `{account_name}.snowflakecomputing.com`   |    [Snowflake documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html)
`warehouse`       | A unique identifier for your virtual warehouse.  |    [Snowflake documentation](https://docs.snowflake.com/en/user-guide/snowflake-manager.html#warehouses-page)
`db`       | A unique identifier for your database.  |    [Snowflake documentation](https://docs.snowflake.com/en/user-guide/snowflake-manager.html#databases-page)

## Snowflake OAuth {: #snowflake-oauth }

### Prerequisites {: #prerequisites }

The following is required before connecting to Snowflake in DataRobot:

* A Snowflake account
* [Snowflake OAuth](https://docs.snowflake.com/en/user-guide/oauth-snowflake.html) configured

### Set up the connection in DataRobot {: #set-up-a-connection-in-datarobot }

When connecting with OAuth parameters, you must create a new data connection.

To set up a data connection using OAuth:

1. Follow the instructions for [creating a data connection](#create-a-new-connection) and [testing the connection](#test-the-connection).

2. After clicking **Test Connection**, a window appears and you must enter your Snowflake client ID and client secret, along with other required details retrieved from Azure app registration configurations (see the example below).

    ![](images/test-connection-sample.png)

3. Click **Save and sign in**.

    ![](images/snowflake-sso-6.png)

3. Enter your Snowflake username and password. Click **Sign in**.

    ![](images/snowflake-sso-7.png)

4. To provide consent to the database client, click **Allow**.

If the connection is successful, the following message appears in DataRobot:

![](images/snowflake-sso-9.png)

### Required parameters {: #required-parameters }

In addition to the required fields listed below, you can learn about other available configuration options in the [Snowflake documentation](https://docs.snowflake.com/en/user-guide/jdbc-parameters.html).

Required field | Description | Documentation
--------------- | ---------- | -----------
_Required fields for data connection_ | :~~: | :~~:
`address`       | A connection object that stores a secure connection URL to connect to Snowflake.<br><br>**Example:**<br> `{account_name}.snowflakecomputing.com`   |    [Snowflake documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html){ target=_blank }
`warehouse`       | A unique identifier for your virtual warehouse.  |   [Snowflake documentation](https://docs.snowflake.com/en/user-guide/snowflake-manager.html#warehouses-page){ target=_blank }
`db`       | A unique identifier for your database.  |   [Snowflake documentation](https://docs.snowflake.com/en/user-guide/snowflake-manager.html#databases-page){ target=_blank }
_Required fields for credentials_ | :~~: | :~~:
Client ID       | The public identifier for your application.  |   [Snowflake documentation](https://docs.snowflake.com/en/user-guide/oauth-custom.html){ target=_blank }
Client secret       | A confidential identifier used to authenticate your application.  |   [Snowflake documentation](https://docs.snowflake.com/en/user-guide/oauth-custom.html){ target=_blank }
Snowflake account name       | A unique identifier for your Snowflake account within an organization.  |   [Snowflake documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html){ target=_blank }

## Snowflake External OAuth {: #snowflake-external-oauth }

### Prerequisites {: #prerequisites }

The following is required before connecting to Snowflake in DataRobot:

=== "Okta"

    * A Snowflake account.
    * [External OAuth](https://docs.snowflake.com/en/user-guide/oauth-snowflake.html){ target=_blank } configured in Snowflake for Okta.

    !!! warning "External OAuth with security integrations"
        If using Okta as the external identity provider (IdP), you must specify `http://localhost/account/snowflake/snowflake_authz_return` as a **Sign-in redirect URI** when [creating a new App integration in Okta](#external-idp-setup).

=== "Azure AD"

    * A Snowflake account.
    * [External OAuth](https://docs.snowflake.com/en/user-guide/oauth-azure){ target=_blank } configured in Snowflake for  Microsoft Azure AD.

    !!! warning "External OAuth with security integrations"
        If using Azure AD as the external identity provider (IdP), you must specify `https://<datarobot_app_server>/account/snowflake/snowflake_authz_return` as a **Redirect URI** when [registering both applications in Azure AD](#external-idp-setup).

###  External IdP setup {: #external-idp-setup }

!!! note
    This section uses example configurations for setting up an external IdP. For information on setting up an external IdP based on your specific environment and requirements, see the documentation for Okta or Azure AD.

In the appropriate external IdP, create the Snowflake application(s):

=== "Okta"

    Create a new App Integration in Okta:

    1. Go to **Applications > Applications**.
    2. Click **Create App Integration**.
    3. For the **Sign-in method**, select **OIDC - OpenID Connect**.
    4. For the **Application type**, select **Web Application**.
    5. Click **Next**.
    6. Make sure the following options are selected:
        * Client Credentials
        * Authorization Code
        * Refresh Token
        * Require consent

    7. Under **LOGIN**, add `http://localhost/account/snowflake/snowflake_authz_return` to the **Sign-in redirect URIs**.
    8. This results in your `Client ID` and `Client secret`.

    Now, create a new Authorization Server:

    1. Go to **Security > API > Add Authorization Server**.

        * Set **Audience** to `https://<partner_name>.snowflakecomputing.com/`. `<partner_name>` is the `datarobot_partner` for the current DataRobot Snowflake instance.

    2. Go to **Scopes > Add Scope**.

        * Set **Name** to `session:role:public` (refers to the Snowflake role).
        * For **Check-in**, add `Require user consent for this scope` and `Block services from requesting this scope`.
        * (Optional) Set the `offline_access` scope to require consent.

    3. Go to **Access Policies > Add Rule** and add the following rules:

        * Add Check-in `Client Credentials`.
        * Add Check-in `Authorization Code`.
        * Add the client integration (created above) to the `Assigned to clients` field.

    4. Go to **Token** and click **Create token**.
    5. This results in the following:

        * `Issuer`, for example, `https://dev-11863425.okta.com/oauth2/aus15ca55wkdOxplJ5d7`.
        * Auth `Token` for programmatic access to the Okta API.
        * Auth server metadata JSON (found in **Settings > Metadata URI**).

    **Okta API calls**

      ``` title="Get current user"
      curl --location --request GET 'https://<OKTA_ACCOUNT>.okta.com/api/v1/users/me' \
      --header 'Accept: application/json' \
      --header 'Content-Type: application/json' \
      --header 'Authorization: SSWS <TOKEN>'
      ```

      ``` title="Get the user's grants"
      curl --location --request GET 'https://<OKTA_ACCOUNT>.okta.com/api/v1/users/<USER_ID>/clients/<CLIENT_ID>/grants' \
      --header 'Accept: application/json' \
      --header 'Content-Type: application/json' \
      --header 'Authorization: SSWS <TOKEN>'
      ```

      ``` title="Revoke grant/consent"
      curl --location --request DELETE 'https://<OKTA_ACCOUNT>.okta.com/api/v1/users/<USER_ID>/grants/<GRANT_ID>' \
      --header 'Accept: application/json' \
      --header 'Content-Type: application/json' \
      --header 'Authorization: SSWS <TOKEN>'
      ```

=== "Azure AD"

    Register an application for Snowflake Resource in Azure AD:

    1. Go to **MS Azure > Azure AD > App registrations**.
    2. Click **New registration**.

        * Under **Name**, enter **Snowflake OAuth Resource**.
        * Under **Supported account types**, select **Accounts in this organizational directory only**.
        * Under **Redirect URI**, select **Web** and enter `https://app.datarobot.com/account/snowflake/snowflake_authz_return`.
        * Click **Register**.
    3. In the Overview section, copy the ClientID from the Application (client) ID field which will be `<OAUTH_CLIENT_ID>` value
    4. Click on Certificates & secrets and then New client secret.
    5. Add a description of the secret.
    4. Click Add and copy the secret. Note that this value will not be available after this step. This will be `<OAUTH_CLIENT_SECRET>` value
    5. Expose the API.

        * Click on the set link next to **Application ID URI** make sure it is a unique ID ( this does not need any change ). This will be the <SNOWFLAKE_APPLICATION_ID_URI> value
        * Click on **Add a scope** to add a scope representing the Snowflake role
        * Enter the scope name as `session:scope:public` ![](images/scope-public.png)

    Register an application for Snowflake Client App in Azure AD:

    1. Go to **MS Azure > Azure AD > App registrations**.
    2. Click **New registration**.

        * Under **Name**, enter **Snowflake OAuth Client**.
        * Under **Supported account types**, select **Accounts in this organizationl directory only**.
        * Under **Redirect URI**, select **Web** and enter `https://app.datarobot.com/account/snowflake/snowflake_authz_return`.
        * Click **Register**.
    3. Go to `API Permission > Add Permission > My APIs > Snowflake Resource` and choose the scope created above for Snowflake Resource (`session:scope:public`).
    4. For programmatic clients that will request an Access Token on behalf of a user, configure Delegated permissions for Applications as follows.

        * Click on API Permissions.
        * Click on Add Permission.
        * Click on My APIs.
        * Click on the Snowflake OAuth Resource that you created in Step 1: Configure the OAuth Resource in Azure AD.
        * Click on the Delegated Permissions box.
        * Check on the Permission related to the Scopes created in step 3 `session:scope:public` 
        * Click Add Permissions. ![](images/oauth-client-api-permissions.png)
    5. Collect additional information for Snowflake integration

        * Click on App Registrations
        * Click on the Snowflake OAuth Resource
        * Click on Endpoints in the Overview interface
        * Copy the OAuth 2.0 token endpoint (v2) which will be `<AZURE_AD_OAUTH_TOKEN_ENDPOINT>` value
        * Copy OpenID Connect metadata url from the endpoint overview and paste it on a new window
        * Locate the "jwks_uri" parameter and copy its value which will be `<AZURE_AD_JWS_KEY_ENDPOINT>` value (e.g., `https://login.microsoftonline.com/6064c47c-80e4-4a2b-82ee-1fc5643b37a2/discovery/v2.0/keys`)
        * Copy Federation metadata document, open the URL in a new window. Locate the "entityID" which will be our `<AZURE_AD_ISSUER>` value (e.g., `https://sts.windows.net/6064c47c-80e4-4a2b-82ee-1fc5643b37a2/`)

    6. This results in the following:

        * `Client ID` and `Client secret` copied from **Snowflake OAuth Resource**
        * Issuer URL copied from step 5 `<AZURE_AD_ISSUER>` value
        * `<AZURE_AD_JWS_KEY_ENDPOINT>` value from Register an application for Snowflake Resource in Azure AD step 5
        * `<SNOWFLAKE_APPLICATION_ID_URI>` from Register an application for Snowflake Resource in Azure AD step 3


??? tip " Related reading"
    - [How to: Create External OAuth Token Using Azure AD On Behalf Of The User](https://community.snowflake.com/s/article/External-oAuth-Token-Generation-using-Azure-AD){ target=_blank }
    - [Configure Microsoft Azure AD for External OAuth](https://docs.snowflake.com/en/user-guide/oauth-azure.html){ target=_blank }

### Snowflake setup {: #snowflake-setup }

!!! note
    This section uses example configurations for setting up an external IdP in Snowflake. For information on setting up an external IdP in Snowflake based on your specific environment and requirements, see the Snowflake documentation.

In Snowflake, create an integration for the appropriate external IdP:

=== "Okta"

    ```
    create security integration external_oauth_okta_2
        type = external_oauth
        enabled = true
        external_oauth_type = okta
        external_oauth_issuer = '<OKTA_ISSUER>'
        external_oauth_jws_keys_url = '<JWKS_URI>'
        external_oauth_audience_list = ('<AUDIENCE>')
        external_oauth_token_user_mapping_claim = 'sub'
        external_oauth_snowflake_user_mapping_attribute = 'login_name';

    CREATE OR REPLACE USER <user_name>
      LOGIN_NAME = '<okta_user_name>';

    alter user <user_name> set DEFAULT_ROLE = 'PUBLIC';
    ```
    <br>

    **Reference values:**

    * `OKTA_ISSUER`: `https://dev-11863425.okta.com/oauth2/aus15ca55wkdOxplJ5d7`
    * `AUDIENCE`: `https://hl91180.us-east-2.aws.snowflakecomputing.com/`
    * `JWKS_URI`: `https://dev-11863425.okta.com/oauth2/aus15ca55wkdOxplJ5d7/v1/keys` (retrieved from Okta Auth server Metadata JSON)
    * `okta_user_name` (retrieved from **Okta > Directory > People**, select a user, and then go to **Profile > Username/login** )

=== "Azure AD"

    !!! note
        You must have the `accountadmin` role, or a role with the global `CREATE INTEGRATION` privilege to create the integration below.
    
    ```
    create security integration external_oauth_azure_1
       type = external_oauth
       enabled = true
       external_oauth_type = azure
       external_oauth_issuer = 'https://sts.windows.net/6064c47c-80e4-4a2b-82ee-1fc5643b37a2/'
       external_oauth_jws_keys_url = 'https://login.microsoftonline.com/6064c47c-80e4-4a2b-82ee-1fc5643b37a2/discovery/v2.0/keys'
       external_oauth_audience_list = ('api://8aa2572f-c9e6-4e91-9eb1-dcd84c856dd2')
       external_oauth_token_user_mapping_claim = 'upn'
       external_oauth_any_role_mode = 'ENABLE'
       external_oauth_snowflake_user_mapping_attribute = 'login_name';
    ```

    Grant access on the integration to the public role:

    `grant USE_ANY_ROLE on integration external_oauth_azure_1 to PUBLIC;`

    Ensure that the `LOGIN_NAME` of the user is the same as the Azure login. Verify using the following query in Snowflake:
    
    `DESC USER <SNOWFLAKE_LOGIN_NAME>`

    If the login names are different, Snowflake cannot validate the access token generated with Azure AD. In that case, use the command below to match Snowflake with Azure:

    `ALTER USER <SNOWFLAKE_LOGIN_NAME> SET LOGIN_NAME='<EMAIL_USED_FOR_AZURE_LOGIN>'`
    

### Set up the connection in DataRobot {: #set-up-the-connection-in-datarobot }

When connecting with external OAuth parameters, you must create a new data connection.

To set up a Snowflake data connection using external OAuth:

1. Follow the instructions for [creating a data connection](#create-a-new-connection) and [testing the connection](#test-the-connection).

2. After clicking **Test Connection**, select your OAuth provider from the dropdown&mdash;either Okta or Azure AD&mdash; and fill in the [additional required fields](#required-parameters).Then, click **Save and sign in**.

    ![](images/snowflake-2.png)

3. Enter your Okta or Azure AD username and password. Click **Sign in**.

4. To provide consent to the database client, click **Allow**.

If the connection is successful, the following message appears in DataRobot:

![](images/snowflake-sso-9.png)

### Required parameters {: #required-parameters }

In addition to the required fields listed below, you can learn about other available configuration options in the [Snowflake documentation](https://docs.snowflake.com/en/user-guide/jdbc-parameters.html){ target=_blank }.

Required field | Description |  Documentation
--------------- | ---------- |  -----------
_Required fields for data connection_ | :~~: | :~~:
`address`       | A connection object that stores a secure connection URL to connect to Snowflake.<br><br>**Example:** `{account_name}.snowflakecomputing.com`   |   [Snowflake documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html){ target=_blank }
`warehouse`       | A unique identifier for your virtual warehouse.  |    [Snowflake documentation](https://docs.snowflake.com/en/user-guide/snowflake-manager.html#warehouses-page){ target=_blank }
`db`       | A unique identifier for your database.  |  [Snowflake documentation](https://docs.snowflake.com/en/user-guide/snowflake-manager.html#databases-page){ target=_blank }
_Required fields for credentials_ | :~~: | :~~:
Client ID       | The public identifier for your application.<br><br>In the Okta Admin console, go to **Applications** > **Applications** > **Your OpenID Connect web app** > **Sign On** tab > **Sign On Methods**.<br><br>In Azure AD, this is also known as the `applicationID`.  | [Okta](https://developer.okta.com/docs/guides/find-your-app-credentials/main/) or [Azure AD](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal){ target=_blank } documentation
Client secret       | A confidential identifier used to authenticate your application.<br><br>In the Okta Admin console, go to **Applications** > **Applications** > **Your OpenID Connect web app** > **Sign On** tab > **Sign On Methods**.<br><br>In Azure AD, this is also known as the `application secret`.  |  [Okta](https://developer.okta.com/docs/guides/find-your-app-credentials/main/){ target=_blank } or [Azure AD](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal){ target=_blank } documentation
Snowflake account name       | A unique identifier for your Snowflake account within an organization.  |   [Snowflake documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html){ target=_blank }
Issuer URL       | A URL that uniquely identifies your SAML identity provider. "Issuer" refers to the Entity ID of your identity provider.<br><br>**Examples:**<br> <ul><li>Okta: `https://<your_company>.okta.com/oauth2/<auth_server_id>`</li><li>Azure AD:<br>`https://login.microsoftonline.com/<snowflake_resource_app_id>`</li></ul>  |   [Okta](https://developer.okta.com/docs/reference/api/oidc){ target=_blank } or [Azure AD](https://docs.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad){ target=_blank } documentation
Scopes       | Contains the name of your Snowflake role. <br><br> **Examples:** <br>Parameters for a Snowflake Analyst. <br> <ul><li>Okta: `session:role:analyst`</li><li>Azure AD: `<client_app_id>/session:scope:analyst`</li></ul>  |   [Snowflake documentation](https://docs.snowflake.com/en/user-guide/oauth-ext-overview.html#scopes){ target=_blank }

Reach out to your administrator for the appropriate values for these fields.

## Caveats {: #caveats }

By default, Snowflake preserves the case of alphabetic characters when storing and resolving double-quoted identifiers; however, if you override this default in Snowflake, double-quoted identifiers are stored and resolved as uppercase letters. Because DataRobot is a case-sensitive platform, it's important to preserve the original case of the letters.

To avoid potential issues related to case-sensitivity, go to your Snowflake data connection in DataRobot, add the `QUOTED_IDENTIFIERS_IGNORE_CASE` parameter, and set the value to `FALSE`. See the [Snowflake documentation](https://docs.snowflake.com/en/sql-reference/parameters.html#quoted-identifiers-ignore-case){ target=_blank } for more details.

{% include 'includes/data-conn-trouble.md' %}
DataRobot returns the following message when testing external OAuth Snowflake connection with Azure AD: <br><br>_AADSTS700016: Application with identifier 'aa2572f-c9e6-4e91-9eb1-dcd84c856dd2' was not found in the directory 'Azure directory "datarobot" ("azuresupportdatarobot")'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant._ | Make sure scopes were created, granted, and assigned to the resource in Azure. | Refer to the [Snowflake setup](#snowflake-setup) section for more details.
DataRobot returns the following message when testing external OAuth after adding the data connection:<br><br>_JDBC connect failed for `jdbc:snowflake://datarobot_partner.snowflakecomputing.com?CLIENT_TIMESTAMP_TYPE_MAPPING=TIMESTAMP_NTZ&db=SANDBOX&warehouse=DEMO_WH&application=DATAROBOT&CLIENT_METADATA_REQUEST_USE_CONNECTION_CTX=false.` Original error: The role requested in the connection or the default role if none was requested in the connection (`ACCOUNTADMIN`) is not listed in the Access Token or was filtered. Please specify another role, or contact your OAuth Authorization server administrator._ | Make sure the user who is establishing a connection with Azure has default role assigned. | The default role needs to be anything other than `ACCOUNTADMIN`, `ORGADMIN`, or `SECURITYADMIN`. If the `session:scope` is created with `scope:role-any`, the user can log in with any role other than the admin roles stated.
DataRobot returns the following message when testing the connection: <br><br>_Invalid Request: The request tokens do not match the user context. Do not copy the user context values (cookies; form fields; headers) between different requests or user sessions; always maintain the `ALL` of the supplied values across a complete single user flow. Failure Reasons:[Token values do not match;]_ | Make sure the login name of the user matches the login name in both Snowflake and Azure to map user and create access tokens. | You can alter the login name in Snowflake to match the username of Azure if it does not already match.