Salesforce API 2段階認証の設定 (API ログインの 2 要素認証)

はじめに
===

Salesforce APIを呼び出す時、Salesforceの2段階認証「API ログインの 2 要素認証」を設定し、Google Authenticatorのワンタイムパスワードを使って、Salesforce APIを呼び出す手順を記します。

概要
===

WebブラウザからSalesforce( https://login.salesforce.com, https://test.salesforce.com/ )へSalesforceユーザでログインする時、Salesforceユーザのパスワード認証に加えて、Google AuthenticatorやSalesforce Authenticatorのワンタイムパスワード(TOTP)を用いて、2段階認証(2 要素認証)を設定する事が出来ます。

Salesforce APIの呼び出し時にも、Google AuthenticatorやSalesforce Authenticatorのワンタイムパスワードを用いて、2段階認証(2 要素認証)を設定する事が出来ます。

環境
===

2段階認証の設定後、Salesforce REST APIの呼び出しは以下のAWS EC2インスタンス(Amazon Linux)で試しました。

http://qiita.com/na0AaooQ/items/a6f733f13a79658da956
http://qiita.com/na0AaooQ/items/157c28a80948c4b97bed

参考資料
===

WebブラウザからSalesforceのコンソール( https://login.salesforce.com/, https://test.salesforce.com/ )へログインする時、2段階認証を設定する手順については、以下を参考にさせて頂きました。

https://help.salesforce.com/HTViewHelpDoc?id=security_require_two_factor_authentication.htm&language=ja
https://help.salesforce.com/HTViewHelpDoc?id=add_time_based_token.htm&language=ja
http://tyoshikawa1106.hatenablog.com/entry/2013/11/04/092928
http://www.terrasky.co.jp/blog/2014/140226_001336.php


Salesforce REST API呼び出し時の2段認証設定の手順
===

Salesforce APIの2段階認証(API ログインの 2 要素認証)を設定する事で、Salesforce REST APIを呼び出す時、Salesforceユーザのパスワードの後ろにGoogle Authenticatorが生成するワンタイムパスワードをつけないとSalesforce APIを呼び出せないよう制限をかける事が可能です。詳細は後述致します。

### (1) https://login.salesforce.com/ へシステム管理者ユーザでログインします。

### (2) 2段階認証を設定したいSalesforceユーザのプロファイルで「API ログインの 2 要素認証」にチェックをつけます。

2段階認証を設定したいSalesforceユーザのプロファイル設定画面で「API ログインの 2 要素認証」にチェックをつけます。

今回の例では、以下のような設定という前提で手順を表記します。

| 設定 | 本手順の例 | 備考 |
|:-----|:------|:-------|
| Salesforce API呼び出し用Salesforceユーザ |  example_salesforce_api_user@hoge.example.com | AWS EC2インスタンスからSalesforce APIを呼び出す時に使用しているSalesforceユーザ |
| Salesforce API呼び出し用Salesforceユーザのプロファイル | テストオブジェクトプロファイル | Salesforce API呼び出し用Salesforceユーザに割り当てているプロファイル |
　
「設定」->「管理」->「ユーザの管理」->「プロファイル」->「テストオブジェクトプロファイル」を選択して「編集」をクリックします。

「一般ユーザ権限」の以下に設定項目にチェックをつけます。

| チェックをつける設定項目 |
|:-----|
| ユーザインターフェースログインの 2 要素認証 |
| API ログインの 2 要素認証 |

### (3) 自分の携帯やPCにGoogle Authenticatorをインストールします。

2段階認証の設定用に、自分の携帯やPCにGoogle Authenticatorをインストールします。
今回の手順では、Android端末にGoogle Authenticatorをインストールして試しました。

iPhone用
https://itunes.apple.com/jp/app/google-authenticator/id388497605?mt=8

Android用
https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=ja

### (4) 自分の携帯にQRコードをスキャンするアプリケーション(QRコードスキャナー)をインストールします。

2段階認証の設定用に、自分の携帯にQRコードスキャナーをインストールします。

今回の手順では、Android端末にQRコードスキャナーをインストールして試しました。

iPhone用
https://itunes.apple.com/jp/app/qrkodorida-for-iphone/id585561686?mt=8

Android用
https://play.google.com/store/apps/details?id=com.google.zxing.client.android&hl=ja


### (5) https://login.salesforce.com/ へSalesforce API呼び出し用のSalesforceユーザでログインします。

Salesforceコンソール( https://login.salesforce.com/ )にSalesforce API呼び出し用のSalesforceユーザ ( example_salesforce_api_user@hoge.example.com )でログインします。

### (6) Salesforceコンソールログイン時に、2段階認証用のQRコードが表示されるので、QRコードをスキャンしてGoogle Authenticatorに追加します。

QRコードスキャナでQRコードをスキャンして、Google AuthenticatorでSalesforce API呼び出し用のSalesforceユーザ ( example_salesforce_api_user@hoge.example.com )のワンタイムパスワードを生成するように設定します。

これで、Salesforce API呼び出し用のSalesforceユーザの2段階認証の設定が完了しました。

### (7) Salesforce APIを呼び出すAWS EC2インスタンス(Amazon Linux)へログインします。

AWS EC2インスタンス(Amazon Linux)へec2-userユーザでsshログインします。

### (8) AWS EC2インスタンス(Amazon Linux)の/home/ec2-user/.bashrcにSalesforce API接続用の環境変数を追加します。

例として、/home/ec2-user/.bashrcにSalesforce API呼び出し用ユーザのパスワードを設定します。

| 設定 | 本手順の例 |
|:-----|:------|
| Salesforce API呼び出し用ユーザ | example_salesforce_api_user@hoge.example.com |
| Salesforce API呼び出し用ユーザのSalesforceコンソールログインパスワード | examplepassword |
| Google AuthenticatorのSalesforce API呼び出し用ユーザのワンタイムパスワード | 123456 |

```
[ec2-user@salesforce-api-test ~]$ vi /home/ec2-user/.bashrc
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# User specific aliases and functions
### Sandbox環境へ接続する場合のAPIエンドポイント
##export DATABASEDOTCOM_HOST="test.salesforce.com"
### 本番環境へ接続する場合のAPIエンドポイント
export DATABASEDOTCOM_HOST="login.salesforce.com"
export DATABASEDOTCOM_CLIENT_ID="3**************************************************************F"
export DATABASEDOTCOM_CLIENT_SECRET="1********************4"
export DATABASEDOTCOM_CLIENT_USERNAME="example_salesforce_api_user@hoge.example.com"
export DATABASEDOTCOM_CLIENT_AUTHENTICATE_PASSWORD="examplepassword"
```

```
[ec2-user@salesforce-api-test ~]$ source /home/ec2-user/.bashrc
[ec2-user@salesforce-api-test ~]$
```

### (9) 2段階認証の設定後、Salesforce APIを呼び出します。

Salesforce APIの2段階認証(API ログインの 2 要素認証)を設定している場合、Salesforce APIを呼び出す時、パスワードの後ろにGoogle Authenticatorが生成するワンタイムパスワードをつける事で、Salesforce APIを呼び出す事が出来ます。

例えばSalesforceユーザのパスワード、ワンタイムパスワードが以下のような場合、Salesforce API呼び出し時のパスワードは「examplepassword123456」となります。

| 設定 | 本手順の例 |
|:-----|:------|
| Salesforce API呼び出し用ユーザのSalesforceコンソールログインパスワード | examplepassword | 
| Google AuthenticatorのSalesforce API呼び出し用ユーザのワンタイムパスワード | 123456 |

実際にSalesforce APIを呼び出してみます。

```
[ec2-user@salesforce-api-test ~]$ export DATABASEDOTCOM_CLIENT_AUTHENTICATE_PASSWORD="examplepassword123456"
[ec2-user@salesforce-api-test ~]$
```

正常にSalesforce APIを呼び出せました。

```
[ec2-user@salesforce-api-test ~]$ curl -s https://$DATABASEDOTCOM_HOST/services/oauth2/token -d "grant_type=password" -d "client_id=$DATABASEDOTCOM_CLIENT_ID" -d "client_secret=$DATABASEDOTCOM_CLIENT_SECRET" -d "username=$DATABASEDOTCOM_CLIENT_USERNAME" -d "password=$DATABASEDOTCOM_CLIENT_AUTHENTICATE_PASSWORD"
{"access_token":"****************************************************************************************************************
","instance_url":"https://ap2.salesforce.com","id":"https://login.salesforce.com/id/******************/*******************","token_type":"Bearer","issued_at":"1474279178027","signature":"Vx+xHtnanlsUZwihpUBNYtphrP6QTwTe02Hw0q5eu9Y="}[ec2-user@salesforce-api-test ~]$
[ec2-user@salesforce-api-test ~]$
```

```
[ec2-user@salesforce-api-test ~]$ DATABASEDOTCOM_ACCESS_TOKEN='****************************************************************************************************************'
[ec2-user@salesforce-api-test ~]$
```

```
[ec2-user@salesforce-api-test ~]$ DATABASEDOTCOM_INSTANCE_URL='https://ap2.salesforce.com'
[ec2-user@salesforce-api-test ~]$
```

```
[ec2-user@salesforce-api-test ~]$ curl -s $DATABASEDOTCOM_INSTANCE_URL/services/data/v24.0/query?q=SELECT+user_name__c%2cuser_email__c%2ccreate_date__c+FROM+QuickStart__c -H "Authorization: Bearer $DATABASEDOTCOM_ACCESS_TOKEN" -H "X-PrettyPrint:1" | jq '.'
{{
  "totalSize": 34,
  "done": true,
  "records": [
    {
      "attributes": {
        "type": "QuickStart__c",
        "url": "/services/data/v24.0/sobjects/QuickStart__c/a032800000FlloBAAR"
      },
      "user_name__c": "テスト太郎",
      "user_email__c": "test.tarou@example.com",
      "create_date__c": null
    },
　(中略)
    {
      "attributes": {
        "type": "QuickStart__c",
        "url": "/services/data/v24.0/sobjects/QuickStart__c/a032800000G7wcLAAR"
      },
      "user_name__c": "Salesforce APIテスト",
      "user_email__c": "example@hoge.example.com",
      "create_date__c": "2016-09-07"
    }
  ]
}
[ec2-user@salesforce-api-test ~]$ {
```

備考
===

Salesforce API 2段階認証を設定したのに(API ログインの 2 要素認証 にチェックをつけたのに)、Google Authenticatorが生成するワンタイムパスワードをつけないでAPIを呼び出そうとした場合、Salesforce API利用時の認証に失敗します。


```
[ec2-user@salesforce-api-test ~]$ export DATABASEDOTCOM_CLIENT_AUTHENTICATE_PASSWORD="examplepassword"
[ec2-user@salesforce-api-test ~]$
```

```
[ec2-user@salesforce-api-test ~]$ curl -s https://$DATABASEDOTCOM_HOST/services/oauth2/token -d "grant_type=password" -d "client_id=$DATABASEDOTCOM_CLIENT_ID" -d "client_secret=$DATABASEDOTCOM_CLIENT_SECRET" -d "username=$DATABASEDOTCOM_CLIENT_USERNAME" -d "password=$DATABASEDOTCOM_CLIENT_AUTHENTICATE_PASSWORD"
{"error":"invalid_grant","error_description":"authentication failure"}[ec2-user@salesforce-api-test ~]$
[ec2-user@salesforce-api-test ~]$
```

***

以上になります。