Azure Data Factory の  web アクティビティにて Salesforce の REST API を利用する際のアクセストークンを取得する方法

## 概要

Azure Data Factory の  web アクティビティにて Salesforce の REST API を利用する際のアクセストークンを取得する方法を共有します。現時点で実装検証が完了している下記の方法におけるアクセストークンの取得方法と無効化の方法を紹介します。

1. [OAuth 2.0 クライアントログイン情報フローによる方法](https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_client_credentials_flow.htm&type=5)
2. [OAuth 2.0 ユーザー名パスワードフローによる方法](https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_username_password_flow.htm&type=5)

OAuth 2.0 ユーザー名パスワードフローについては Salesforce のドキュメントにて下記のように記述されているため、OAuth 2.0 クライアントログイン情報フロー（あるいは、OAuth 2.0 Web サーバーフロー）を利用することが推奨されています。

> 重要 セキュリティを強化するために、ユーザー名パスワードフローの代わりに、コード交換の証明鍵 (PKCE) を使用する OAuth 2.0 Web サーバーフロー、または OAuth 2.0 クライアントログイン情報フローを使用することをお勧めします。

引用元：[特別なシナリオの OAuth 2.0 ユーザー名パスワードフロー (salesforce.com)](https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_username_password_flow.htm&type=5)

この記事では、インテグレーションユーザーと接続アプリを作成していることを前提としています。

## 手順

### 1. OAuth 2.0 クライアントログイン情報フローによる方法

#### 1-1. アクセストークンの取得

下記の設定をした web アクティビティを追加します。OAuth 2.0 ユーザー名パスワードフローによる方法とは、 URL が異なることに注意してください。

| #    | 項目     | 値                                                           |
| ---- | -------- | ------------------------------------------------------------ |
| 1    | URL      | https://{DomainName}.my.salesforce.com/services/oauth2/token |
| 2    | メソッド | POST                                                         |
| 3    | 本文     | grant_type=client_credentials&client_id={ClientId}&client_secret={ClientSecret} |
| 4    | ヘッダー | Content-Type: application/x-www-form-urlencoded              |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d1e8abb9-2dad-6fa7-f205-8184fdd8ccbd.png)

#### 1-2. アクセストークンの無効化

下記の設定をした web アクティビティを追加します。

| #    | 項目     | 値                                                           |
| ---- | -------- | ------------------------------------------------------------ |
| 1    | URL      | https://{DomainName}.my.salesforce.com/services/oauth2/revoke |
| 2    | メソッド | POST                                                         |
| 3    | 本文     | token={AccessToken}                                          |
| 4    | ヘッダー | Content-Type: application/x-www-form-urlencoded              |

アクセストークンは、下記のような式により前の手順で設定した Web アクティビティの出力結果をセットします。

```text
@concat(
    'token=',
    activity('GetToken').output.access_token
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/aa33e243-7760-95ec-6d24-8db9080f3350.png)

#### 1-3. 動作確認

デバック実行を行い、アクセストークン等を取得していることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/b1065eed-ec1b-c7da-63cc-f48f55213623.png)

### OAuth 2.0 ユーザー名パスワードフローによる方法

#### 2-1. アクセストークンの取得方法

下記の設定をした web アクティビティを追加します。

| #    | 項目     | 値                                                           |
| ---- | -------- | ------------------------------------------------------------ |
| 1    | URL      | https://login.salesforce.com/services/oauth2/token           |
| 2    | メソッド | POST                                                         |
| 3    | 本文     | grant_type=password&client_id={ClientId}&client_secret={ClientSecret}&username={UserName}&password={Password}{SecurityToken} |
| 4    | ヘッダー | Content-Type: application/x-www-form-urlencoded              |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0666a884-d8fa-0411-78d5-531057553a91.png)

#### 2-2. アクセストークンの無効化

| #    | 項目     | 値                                                           |
| ---- | -------- | ------------------------------------------------------------ |
| 1    | URL      | https://login.salesforce.com/services/oauth2/revoke |
| 2    | メソッド | POST                                                         |
| 3    | 本文     | token={AccessToken}                                          |
| 4    | ヘッダー | Content-Type: application/x-www-form-urlencoded              |

アクセストークンは、下記のような式により前の手順で設定した Web アクティビティの出力結果をセットします。

```text
@concat(
    'token=',
    activity('GetToken').output.access_token
)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/4a329db1-ac44-cb2e-b6d3-838bdb745abb.png)

#### 2-3. 動作確認

デバック実行を行い、アクセストークン等を取得していることを確認してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/da21296d-b8e7-1335-803e-6e5c2290af8b.png)

## 本場利用に向けたパイプラインの改善

### OAuth 2.0 クライアントログイン情報フローによる方法の改善

#### 1. Client ID と Client Secret を Key Vault に格納

```text
@concat(
    'grant_type=client_credentials',
    '&client_id=',
    activity('GetSFDCClientId').output.Value,
    '&client_secret=',
    activity('GetSFDCClientSecret').output.Value
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f62b66cc-d9e7-e2a6-2750-29836d69797a.png)

#### 2. トークンを取得と無効化の web アクティビティにて`インライン`から`リンクサービス`に変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/15d5969b-d396-ae45-3a0e-7f54dbcc4890.png)

#### 3. Key Vault の取得値やアクセストークンなどの出力と入力を`セキュリティで保護された出力`と`セキュリティで保護された入力`に変更

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0d136875-5454-6f99-8d2b-1a3bf6179010.png)