Salesforce JWT用の接続アプリを共有して組織への接続を簡単にする

## 概要

CI環境でSalesforce CLIを使う場合や、Herokuなどの外部アプリから固定のユーザでSalesforceに接続するような場合、あらかじめ組織に証明書を登録した接続アプリケーションを作成しておき、対応する秘密鍵ファイルからJWTを生成して[JWT Bearer Token フロー](https://qiita.com/stomita/items/4542ce1b48e5fa849ef1)で接続するのが常套手段です。

ただ、接続先の組織が変わるたび、先に接続アプリケーションを組織に用意しておかなければいけないのは少し面倒です。（証明書と鍵ファイルは共有するとしても）接続アプリケーションが変わってしまうとClient IDが変わるので、接続クライアント側の情報の管理も煩雑になりますし、また、登録した証明書情報をアップデートする必要がある場合に、いちいちすべての組織で作成した接続アプリケーションに対して設定するのはとても大変なことです。

ここでは、ある組織で作成したJWT接続用の接続アプリケーションを、「インストール」することで組織間で共有する方法について記します。これにより共通の接続アプリを用いて任意の組織にJWT grantで接続することが可能になり、セットアップが簡単になります。

## 手順

### 接続アプリケーションの作成

まず、とりあえずいずれかの組織で接続アプリケーション情報を作成します。これは実際にJWT接続しようとする組織上でなくても構いません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/6495/d388572e-980a-3cbe-af6a-b3ad5d8a7f64.png)


ここで、コールバックURLには `http://localhost:1717/OauthRedirect` を設定しておきます。
デジタル署名には、あらかじめ作成した証明書ファイルをアップロードして設定します。
証明書ファイルおよび鍵ファイルの作り方は[Salesforce CLIのオフィシャルガイド](https://developer.salesforce.com/docs/atlas.ja-jp.sfdx_dev.meta/sfdx_dev/sfdx_dev_auth_key_and_cert.htm)にありますのでそちらを参照してください。

作成された接続アプリケーションのコンシューマ鍵(Client ID)およびコンシューマの秘密(Client Secret)は記録しておきます。

### OAuth2で対象組織にログイン

上記の接続アプリを作成したら、ひとまず通常のOAuth2のフローを利用して対象となる組織にログインします。ここでは、OAuth2クライアントとしてSalesforce CLIを利用します。

Salesforce CLIでは `force:auth:web:login` コマンドで、ブラウザを表示してのログインができます。その際、`--clientid`(`-i`)オプションで、先のステップで作成した接続アプリのClient IDを指定します。
Client Secretをプロンプトされるので、同じく先の接続アプリのClient Secretを入力します。

```sh
$ sfdx force:auth:web:login -i 3MVG9pe..(snip)..KpDz6
OAuth client secret of personal connected app?: ********************************
```

オープンしたWebブラウザ上で接続先の組織の管理者ユーザ名/パスワードを入力してログインして完了です。上記コマンドを実行したターミナル上に

```
Successfully authorized username@yourorg.example.org with org ID 00D00000000000000
```

などと表示されているはずです。


### 接続アプリのインストール

続いて、ログインした組織上で、接続アプリのインストールを行います。
設定画面を開き、クイック検索ボックスから「接続アプリケーション」と入力し、「接続アプリケーションの OAuth の利用状況」メニューを選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/6495/6e4b49aa-fa67-2deb-0e1f-b9139c0c78ea.png)

先程OAuthログインした接続アプリの情報が表示されているかと思いますので、その接続アプリの「インストール」ボタンをクリックします。一旦確認メッセージが表示されるので、「インストール」をクリックします。

つづいて、表示された接続アプリケーションの情報の「ポリシーを編集」をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/6495/33fa9fdb-819b-9d97-76bb-32a38c25589e.png)

「許可されているユーザ」の値を「管理者が承認したユーザは事前承認済み」に設定します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/6495/45712405-8817-fc48-aace-4d7294393af1.png)

「保存」ボタンを押してポリシーを変更します。なお、この際に一旦ログイン接続が中断される場合がありますが、その場合は再度ログインしてください。

最後に、プロファイルのセクションで、実際にJWTで接続する必要のあるプロファイルを選択しておきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/6495/9c08e266-d8e6-f1c3-1bf4-f94f13570f73.png)

### `force:auth:jwt:grant`で対象組織に接続

ここまでセットアップできたら、いよいよJWTでの接続を試します。同じくSalesforce CLIを用いますが、さきほどOAuthですでにログインしてしまっているので、一度ログアウトしておきます。

```sh
$ sfdx force:auth:logout -u username@yourorg.example.org
```

続いて、接続アプリ登録時に取得したClient IDおよび作成した鍵ファイルを指定して、`force:auth:jwt:grant` コマンドで接続します。

```sh
$ sfdx force:auth:jwt:grant -i 3MVG9pe..(snip)..KpDz6 -f ./path/to/server.key -u username@yourorg.example.org
Successfully authorized username@yourorg.example.org with org ID 00D00000000000000
```

以上のように表示されていれば無事ログインされたことになります。

## まとめ

JWTトークンでSalesforceの接続を行うのは、従来の方法に比べて手順が煩雑にみえるので、躊躇している方も多いと思います。

今回提案した方法は、一つの接続アプリと証明書・鍵ファイルさえ管理しておけば、すべての組織の接続に利用できる、というところがポイントです。これにより運用管理がとてもシンプルになります。

特に、闇雲にオフィシャルの手順に沿っていると、毎回組織に接続するたびに接続アプリどころかOpenSSLで鍵生成してたりしてしまうこともありますが、それだとあまり証明書ベースの認証の意味がありません。JWTを利用した証明書ベースの認証は一旦構築してしまえばかなりお手軽なので、ぜひトライしてみて下さい。