> ## Documentation Index
> Fetch the complete documentation index at: https://docs.domino.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Set up OAuth for Snowflake

Use this topic to enable users to create OAuth-backed [Snowflake Data Sources](/cloud/platform-capabilities/core-concepts/data/data-source-connectors/connect-to-snowflake), and authenticate and query Snowflake with a JWT token. After this is set up, users can select **OAuth** when they create a Snowflake Data Source.

When an OAuth-configured Snowflake is queried in a Domino execution, the `dominodatalab-data` library uses the Domino JWT token to authenticate against the underlying Snowflake database. If this is set up properly, no extra user action is needed.

To set up Snowflake OAuth, you must:

1. Set up an External OAuth Security Integration in your Snowflake account to [configure Snowflake](#1-configure-snowflake). This dictates what values your Snowflake account will expect to be propagated inside the token for successful authentication.

2. [Set up Keycloak](#2-set-up-keycloak-integration) to ensure correct propagation of the necessary values in the Domino JWT access token.

<Note>
  OAuth is not supported for service accounts. OAuth-authenticated connections can be used for any execution type *except* Domino endpoints.
</Note>

<Note>
  Because authentication depends on the Domino JWT token propagating the correct set-up values in the context of an execution, you cannot verify successful authentication when you create a Data Source. Therefore, the green checkmark that shows when you create a Data Source does not guarantee that authentication will succeed. To confirm successful value propagation in a Domino JWT token, use the `dominodatalab-data` library to query data from an OAuth Data Source in a Domino execution, such as a Workspace.
</Note>

## 1. Configure Snowflake

To set up an External OAuth Security Integration in Snowflake, see the [Snowflake documentation](https://docs.snowflake.com/en/user-guide/oauth-ext-custom.html#configure-custom-clients-for-external-oauth). Get familiar with the Snowflake terminology and the values that Snowflake needs in the token; correct spelling of the values is critical.

The following is a sample command to create a base security integration that allows all account roles to successfully authenticate. You can use this as a starting point to build an authentication configuration that fits your security needs.

```sql theme={null}
create security integration <external_oauth_name>
    type = external_oauth
    enabled = true
    external_oauth_type = custom
    external_oauth_issuer = 'https://<domino-domain>/auth/realms/DominoRealm'
    external_oauth_rsa_public_key = <keycloak-realm-settings-public-key>
    external_oauth_audience_list=('account')
    external_oauth_scope_mapping_attribute = 'scp'
    external_oauth_token_user_mapping_claim='preferred_username_snowflake'
    external_oauth_snowflake_user_mapping_attribute='login_name';

alter security integration <external_oauth_name> set EXTERNAL_OAUTH_ANY_ROLE_MODE = ENABLE;
```

Find the value for these keys:

* `external_oauth_issuer` in Keycloak’s **Realm Settings** > **OpenID Endpoint Configuration** > **Issuer**

* `external_oauth_rsa_public_key` in Keycloak’s **Realm Settings** > **Keys** > **Public Key from RS256**

The configured security integration (`desc security integration <external_oauth_name>`) should look similar to the following:

<img src="https://mintcdn.com/dominodatalab-e871cec4/O7LjTllMke2wnkZN/images/5.2/datasources/security_integration.png?fit=max&auto=format&n=O7LjTllMke2wnkZN&q=85&s=eb3dbd42fc2ddb67179bbffe8d470997" alt="Snowflake Security Integration" width="2798" height="1220" data-path="images/5.2/datasources/security_integration.png" />

## 2. Set up Keycloak integration

The following steps describe how to instruct Keycloak to pass the values that Snowflake’s custom security integration expects in the Domino JWT access token. To do this, create mappers in the `domino-play` client and specify the option to `add to access token` in each mapper. This creates a key-value entry in the Domino JWT token with key being what is specified under `Token Claim Name`.

The value depends on what type of mapper is created. For example, a hardcoded-claim mapper requests a value, which ultimately propagates equally to all users. By contrast, a user-attribute mapper requests a `User Attribute` name, then looks into each Keycloak user attribute for that attribute name and propagates its value. This lets you customize how the Domino JWT token is augmented by each user.

The following is a base solution that matches the base Snowflake custom security integration described previously. This solution is a starting point to build upon for a customized authentication configuration that fits your security needs.

Set up the Keycloak integration:

1. Go to the keycloak admin console at `https://<domino-domain>/auth/`.

2. Click **Domino Realm** > **Clients**.

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/datasources/dashboard.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=ca3483c59abb73015d885041a82168a1" alt="Keycloak Client Dashboard" width="2337" height="798" data-path="images/6.1/datasources/dashboard.png" />

3. From the lookup list, click **domino-play**, then click **Client scopes** > **domino-play-dedicated**.

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/admin-guide/client-scopes.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=ff171e5ed17d51b07f1802fb48ff4c6a" alt="Client Scopes" width="1608" height="761" data-path="images/6.1/admin-guide/client-scopes.png" />

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/admin-guide/mappers.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=8ad138e75d98f569d7b7e99db3f4ac03" alt="Mappers" width="1355" height="886" data-path="images/6.1/admin-guide/mappers.png" />

4. To add mappers, click **Mappers** > **Add mapper** > **By configuration**.

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/admin-guide/add-mappers.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=e23dbb293d2d1c8ab4b1e747e4de69a7" alt="Add mappers" width="1628" height="946" data-path="images/6.1/admin-guide/add-mappers.png" />

5. Choose a mapper from the listed mappings and configure the new mapper.

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/admin-guide/configure-mappers.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=deb33b9747d8b3abc33f33cd5e95479c" alt="Configure mappers" width="1709" height="1064" data-path="images/6.1/admin-guide/configure-mappers.png" />

   The mappers are simple examples. For the `scp` claim specifically, it is highly recommended that you make use of the prepopulated "Scope Claim Aggregator" mapper. Otherwise you can write your mappers differently, as long as they conform to the Snowflake Security Integration’s requirements.

   <table>
     <thead>
       <tr>
         <th colSpan="2" style={{textAlign: 'left'}}>SCP</th>
       </tr>
     </thead>

     <tbody>
       <tr>
         <td><p>Token Claim Name</p></td>
         <td><p><code>scp</code></p></td>
       </tr>

       <tr>
         <td><p>User Attribute</p></td>
         <td><p>The name of the user attribute containing the desired Snowflake scope name.</p></td>
       </tr>

       <tr>
         <td><p>Static Values (comma-separated)</p></td>
         <td><p><code>all</code></p></td>
       </tr>

       <tr>
         <td><p>Add to access token</p></td>
         <td><p><code>ON</code></p></td>
       </tr>
     </tbody>
   </table>

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/datasources/scp.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=e9d20cdd5f3cdf1a8ed9f44631ddc5fc" alt="SCP Mapper" width="1375" height="825" data-path="images/6.1/datasources/scp.png" />

   <table>
     <thead>
       <tr>
         <th colSpan="2" style={{textAlign: 'left'}}>Issuer</th>
       </tr>
     </thead>

     <tbody>
       <tr>
         <td><p>Token Claim Name</p></td>
         <td><p><code>external\_oauth\_issuer</code></p></td>
       </tr>

       <tr>
         <td><p>Claim JSON Type</p></td>
         <td><p><code>String</code></p></td>
       </tr>

       <tr>
         <td><p>Add to access token</p></td>
         <td><p><code>ON</code></p></td>
       </tr>

       <tr>
         <td><p>Claim value</p></td>
         <td><p>The name of your OpenID Endpoint Configuration issuer. You can find the value in <strong>Realm Settings</strong> > <strong>OpenID Endpoint Configuration</strong> > <strong>Issuer</strong>.</p></td>
       </tr>
     </tbody>
   </table>

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/datasources/issuer.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=2af43f8f83bd44174138caf422b7a53b" alt="Issuer" width="1479" height="957" data-path="images/6.1/datasources/issuer.png" />

   <table>
     <thead>
       <tr>
         <th colSpan="2" style={{textAlign: 'left'}}>Audience</th>
       </tr>
     </thead>

     <tbody>
       <tr>
         <td><p>Token Claim Name</p></td>
         <td><p><code>external\_oauth\_audience\_list</code></p></td>
       </tr>

       <tr>
         <td><p>Claim JSON Type</p></td>
         <td><p><code>String</code></p></td>
       </tr>

       <tr>
         <td><p>Add to access token</p></td>
         <td><p><code>ON</code></p></td>
       </tr>

       <tr>
         <td><p>Multivalued</p></td>
         <td><p><code>ON</code></p></td>
       </tr>

       <tr>
         <td><p>Claim value</p></td>
         <td><p>This should be a list of audiences supported by the security integration.</p></td>
       </tr>
     </tbody>
   </table>

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/datasources/aud.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=58d5c2108bc4e451a283a3f9eff85eef" alt="Audience Mapper" width="1398" height="995" data-path="images/6.1/datasources/aud.png" />

   <table>
     <thead>
       <tr>
         <th colSpan="2" style={{textAlign: 'left'}}>User Mapping</th>
       </tr>
     </thead>

     <tbody>
       <tr>
         <td><p>Token Claim Name</p></td>
         <td><p><code>external\_oauth\_user\_mapping\_claim</code></p></td>
       </tr>

       <tr>
         <td><p>Claim JSON Type</p></td>
         <td><p><code>String</code></p></td>
       </tr>

       <tr>
         <td><p>Add to access token</p></td>
         <td><p><code>ON</code></p></td>
       </tr>

       <tr>
         <td><p>Claim value</p></td>
         <td><p>This should represent the mapping between keycloak user and Snowflake user.</p></td>
       </tr>
     </tbody>
   </table>

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/datasources/external_user_mapping_claim.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=3de6c0c80f2e4f4293d96967d7cbd893" alt="External User Mapper" width="1383" height="948" data-path="images/6.1/datasources/external_user_mapping_claim.png" />

   <table>
     <thead>
       <tr>
         <th colSpan="2" style={{textAlign: 'left'}}>External User Mapping Attribute</th>
       </tr>
     </thead>

     <tbody>
       <tr>
         <td><p>Token Claim Name</p></td>
         <td><p><code>preferred\_username\_snowflake</code></p></td>
       </tr>

       <tr>
         <td><p>Claim JSON Type</p></td>
         <td><p><code>String</code></p></td>
       </tr>

       <tr>
         <td><p>Add to access token</p></td>
         <td><p><code>ON</code></p></td>
       </tr>

       <tr>
         <td><p>Claim value</p></td>
         <td><p>This is a mapper that goes with your custom security integration. Its value is the Snowflake username of the authenticating user. Note how in the Snowflake custom security integration, we specified <code>external\_oauth\_token\_user\_mapping\_claim='preferred\_username\_snowflake'</code>, instructing Snowflake to use the value of the key <code>preferred\_username\_snowflake</code>.</p></td>
       </tr>
     </tbody>
   </table>

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/datasources/snowflake-preferred-username.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=2976bca8f4bbb305721c3a96fbac56b9" alt="Preferred Username Mapper" width="1372" height="995" data-path="images/6.1/datasources/snowflake-preferred-username.png" />

   <table>
     <thead>
       <tr>
         <th colSpan="2" style={{textAlign: 'left'}}>RSA Public Key Value</th>
       </tr>
     </thead>

     <tbody>
       <tr>
         <td><p>Token Claim Name</p></td>
         <td><p><code>external\_oauth\_rsa\_public\_key\_value</code></p></td>
       </tr>

       <tr>
         <td><p>Claim JSON Type</p></td>
         <td><p><code>String</code></p></td>
       </tr>

       <tr>
         <td><p>Add to access token</p></td>
         <td><p><code>ON</code></p></td>
       </tr>

       <tr>
         <td><p>Claim value</p></td>
         <td><p>This should be the name of your OpenID Endpoint Configuration issuer. You can find the value in <strong>Realm Settings</strong> > <strong>Keys</strong> > <strong>Public Key from RS256</strong></p></td>
       </tr>
     </tbody>
   </table>

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/datasources/rsa_pk.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=fd1853ce65d5b932f93e7cfbfa0a42f1" alt="PK Mapper" width="1380" height="938" data-path="images/6.1/datasources/rsa_pk.png" />

   <table>
     <thead>
       <tr>
         <th colSpan="2" style={{textAlign: 'left'}}>External User Mapping Attribute</th>
       </tr>
     </thead>

     <tbody>
       <tr>
         <td><p>Token Claim Name</p></td>
         <td><p><code>external\_oauth\_snowflake\_user\_mapping\_attribute</code></p></td>
       </tr>

       <tr>
         <td><p>Claim JSON Type</p></td>
         <td><p><code>String</code></p></td>
       </tr>

       <tr>
         <td><p>Add to access token</p></td>
         <td><p><code>ON</code></p></td>
       </tr>

       <tr>
         <td><p>Claim value</p></td>
         <td><p>This is the attribute that is used to map the access token to a Snowflake user record.</p></td>
       </tr>
     </tbody>
   </table>

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/datasources/user_mapping_attr.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=3a174b2301379eceb3e883bb342bfb1f" alt="User Mapping Mapper" width="1390" height="952" data-path="images/6.1/datasources/user_mapping_attr.png" />

   Keycloak propagates the values obtained by the mappers into the JWT token that is used to authenticate against the External OAuth Security Integration you created in Snowflake.

6. If you added a mapper that required a user attribute, add the proper user attribute at **Users** > **View All Users** > **\&lt;user ID>** > **Attributes**.

   You can also automate this to create further roles and mappers, as in this example user attribute:

   <img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/datasources/user_attr.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=f44a50d3c2ab5bbe113990c83a1d11e4" alt="User Attribute" width="1345" height="696" data-path="images/6.1/datasources/user_attr.png" />

7. Add OAuth to the available authentication types for Snowflake:

   1. Go to **Platform settings** > **Configuration records**.

   2. Click **Add Record**.

   3. Enter the `com.cerebro.domino.datasource.SnowflakeConfig.enabledAuthTypes` key with the value `OAuth` or `Basic, OAuth`. The order of the values matters, and the first value will be set as default authentication method for all users.

      <img src="https://mintcdn.com/dominodatalab-e871cec4/O7LjTllMke2wnkZN/images/5.2/datasources/cc_setting.png?fit=max&auto=format&n=O7LjTllMke2wnkZN&q=85&s=9b1aed4c0e39a25ac69d1efa3f4c08c7" alt="CC-Sample" width="2006" height="126" data-path="images/5.2/datasources/cc_setting.png" />

8. Click **Create**.

## 3. Test the configuration

There are two ways to inject user attributes for testing (the user attributes `SCP`, `external_oauth_audience_list`, and `preferred_username_snowflake` must be present in the Domino user JWT token):

* Locally in Keycloak:\
  For quick testing. User attributes can be manually added under the Keycloak user.

* Inject via SAML attributes:\
  For enterprise-level implementations. The recommended way to pass the user attributes is from the Identity Provider as SAML attributes. When SAML attributes include the user attributes, additional mappers are needed to extract them and make them available for the Domino play client.

Three IDP user attribute mappers must be configured:

1. Go to **Domino realm** > **Identity providers** > **Identity provider** > **Mappers**.

2. For the **Mapper type**, select `Attribute importer`.

3. In the **Attribute Name** and **User Attribute Name** fields, add the user attributes to be passed to the Domino play client, for example, `SCP`, `external_oauth_audience_list`, and `preferred_username_snowflake`.

<img src="https://mintcdn.com/dominodatalab-e871cec4/LnFGSZ2o5jkxCrWN/images/6.1/datasources/snowflake-oauth.png?fit=max&auto=format&n=LnFGSZ2o5jkxCrWN&q=85&s=47ea5d77a3aeb05a565f477fd5bf5329" alt="Edit the Identity Provider Mapper" width="1392" height="723" data-path="images/6.1/datasources/snowflake-oauth.png" />

To test that OAuth is working with your Snowflake Data Source, follow these steps:

1. Register a Snowflake Data Source.

2. Select `OAuth` as the authentication type.

3. Open an execution.

4. Query data from the registered Data Source.

<Tip>
  To get the token itself, make a GET request to the [Domino API Proxy](/cloud/reference/api/domino-api-authentication#_use_the_api_proxy_for_domino_api_authentication) by running `curl $DOMINO_API_PROXY/access-token` in an execution like in a terminal of a Workspace or a script of a Job. You can use [https://jwt.io/](https://jwt.io/) to copy/paste the token and see what is and is not being propagated correctly into the Domino JWT token from Keycloak.
</Tip>
