BoxとServiceNow連携：認証方法

# 概要
ServiceNowは、ITプロセスと資産の管理を含む包括的なプラットフォームです。Boxをコンテンツ管理レイヤーとして利用することで、便利なコラボレーション機能やセキュリティ機能が活用でき、ServiceNowの機能がさらに強化されることが期待されます。

以下は考えられる使用例です：
- ServiceNowへのファイルアップロード時に自動的に適切なBoxフォルダへ移行します
- Box運用操作を自動化します（例：ユーザーおよびフォルダ作成、コラボレーション変更）

ServiceNowとBoxを連携する際は、HTTPリクエスト経由でServiceNowからBox APIへ接続します。ただし最初に認証手順が必要です。Box APIでは3つの認証方法がサポートされています：
- ユーザー認証
- サーバ認証（CCG）
- サーバ認証（JWT）

上記3つの方法いずれかでServiceNowからBoxと接続可能ですが、それぞれ異なる手順で設定する必要があります。この記事では具体的な手順を解説します。

# 準備

Boxと連携する際に、開発者コンソールでアプリを作成することが必要です。
開発環境は[開発者サイト](https://developer.box.com/)でアカウントが作成できます。

ServiceNowの開発環境も必要で、[開発者サイト](https://developer.servicenow.com/)でアカウントが作成できます。

# ServiceNowとBox連携の認証方法

以下、3つの認証方法の設定仕方を解説します：
- ユーザー認証
- サーバ認証（CCG）
- サーバ認証（JWT）


Boxガイドで[認証方法の比較](https://ja.developer.box.com/guides/authentication/select/#%E6%AF%94%E8%BC%83)がありますので、ユースケースに合わせて適切な認証方法を選択してください。

:::note warn
ユーザー認証はバッチ処理などの自動的に行うプロセスに向いていませんので、その場合はサーバ認証を利用することが推奨されます。詳細はBoxの[Fair Use Policy](https://www.box.com/legal/fairusepolicy)を参考にしてください。
:::

## ユーザー認証

### 準備
Box開発者コンソールで[OAuth2.0認証アプリ](https://ja.developer.box.com/guides/authentication/oauth2/)を以下の設定で作成します：
- アプリ名：<任意の名前>（例：ServiceNowユーザー認証）
- 「構成」タブでのリダイレクトURI：https://[instance_number].service-now.com/oauth_redirect.do

:::note warn
リダイレクトURIはServiceNowでアプリケーションレジストリを作成する際に生成されますが、以上のパターンになり、instance_numberはServiceNowのURLからも取得できます。
:::

アプリ作成後、「構成」タブでクライアントIDとクライアントシークレットが表示されます。これらをServiceNowのアプリケーションレジストリを作成する際に利用します。

### アプリケーションレジストリを作成
ユーザー認証でBoxと繋がるために、以下の設定でServiceNow上のアプリケーションレジストリ（「サードパーティ OAuth プロバイダーに接続」）を作成します。
- 名前：<任意の名前>（例：Boxユーザー認証）
- クライアントIDとクライアントシークレット：Box上でユーザー認証アプリの作成時に保存しておいたものを利用します
- デフォルトの権限許可タイプ：認証コード
- 認証URL：https://account.box.com/api/oauth2/authorize
- トークンURL：https://api.box.com/oauth2/token
- リダイレクトURL（自動的に生成されます）：https://[instance_number].service-now.com/oauth_redirect.do

![ユーザー認証アプリケーションレジストリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/2f46afd9-2222-fb06-7029-3ccfcc4e8e38.png)

アプリケーションレジストリを保存すると、OAuthエンティティプロファイルが作成されます。そのプロファイルの権限許可タイプは「認証コード」になっているか確認します。

これでユーザー認証の設定が完了します。

## サーバ認証：クライアント資格情報許可（CCG）

### 準備

Box開発者コンソールで[クライアント資格情報許可アプリ](https://ja.developer.box.com/guides/authentication/client-credentials/)を以下の設定で作成します：
- アプリ名：<任意の名前>（例：ServiceNowサーバ認証（CCG））
- 「構成」タブでのアクセスレベルとスコープ：アプリの要件に応じますが、この記事で行うテストのためにデフォルトの設定を変更しません。

サーバ認証アプリの場合は、Box管理者による承認が必要で、設定後「承認」タブで承認を依頼します。管理者が承認したら、アプリのサービスアカウントが生成され、「一般設定」タブでサービスアカウントのメールアドレス（Service Account ID）を確認できます。

アプリ作成後、「構成」タブでクライアントIDとクライアントシークレットが表示されます。これらをServiceNowのアプリケーションレジストリを作成する際に利用します。

ServiceNow側では、クライアント資格情報許可（CCG）で認証する時に[エンタープライズID（もしくは、アプリケーションユーザーID）を指定する必要があります](https://ja.developer.box.com/guides/authentication/client-credentials/#%E5%88%A9%E7%94%A8%E6%96%B9%E6%B3%95)。
ただし、ServiceNowのアプリケーションレジストリ画面で認証リクエストの本文にパラメータを追加することができませんので、[スクリプトインクルードを利用し](https://docs.servicenow.com/ja-JP/bundle/tokyo-api-reference/page/app-store/dev_portal/API_reference/OAuthUtil/concept/c_OAuthUtilScriptInclude.html)、認証リクエストの本文を編集します。
新規スクリプトインクルードを作成し、以下のコードを使い、OAuthBoxCCGの名前で保存します。

```javascript:OAuthBoxCCG
var OAuthBoxCCG = Class.create();
OAuthBoxCCG.prototype = Object.extendsObject(OAuthUtil, {

    preprocessAccessToken: function(requestParamMap) {
		requestParamMap.put("box_subject_type", "enterprise");
		requestParamMap.put("box_subject_id", "123456789");
    },

    type: 'OAuthBoxCCG'
});
```

:::note warn
上記のコードにあるbox_subject_idの値（"123456789"）をエンタープライズIDにします。
:::

:::note warn
スクリプト名は任意ですが、アプリケーションレジストリーで利用するために、"OAuth"から始まる必要があります。
:::

### アプリケーションレジストリを作成

サーバ認証（CCG）でBoxと繋がるために、以下の設定でServiceNow上のアプリケーションレジストリ（「サードパーティ OAuth プロバイダーに接続」）を作成します：
- 名前：<任意の名前>（例：Boxサーバー認証（CCG））
- クライアントIDとクライアントシークレット：Box上でクライアント資格情報許可アプリの作成時に保存しておいたものを利用します
- デフォルトの権限許可タイプ：クライアント資格情報
- トークンURL：https://api.box.com/oauth2/token
- OAuth APIスクリプト：作っておいたスクリプトインクルードを選択します（例：OAuthBoxCCG）

![サーバ認証（CCG）アプリケーションレジストリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/58398a93-856b-7686-69a6-8428269c0007.png)

アプリケーションレジストリを保存すると、OAuthエンティティプロファイルが作成されます。そのプロファイルの権限許可タイプは「クライアント資格情報」になっているか確認します。

これでサーバ認証（CCG）の設定が完了します。

## サーバ認証：JSONウェブトークン（JWT）

このセクションで解説する方法は[ServiceNowガイド](https://developer.servicenow.com/blog.do?p=/post/integrating-servicenow-to-box-with-jwt/)の方法をベースにしています。

### 準備

ServiceNowでJWT認証を利用するには、[Javaキーストア証明書アップロードやJWT署名キーを作成する必要があります](https://docs.servicenow.com/ja-JP/bundle/vancouver-platform-security/page/administer/security/task/JWT-Bearer-token-support.html)。そのための準備として、事前にコマンドラインで[keytool](https://docs.oracle.com/javase/jp/6/technotes/tools/windows/keytool.html)と[openssl](https://www.openssl.org/)を使って、キーストアとRSA公開キーを生成します。生成される`box.jks`はServiceNow上で設定する際に利用して、`box.pub`はBox上でカスタムアプリを作成する際に利用します。

```bash
# キーストアを生成する（キーストアパスワードを設定する）
keytool -genkeypair -keyalg rsa -keysize 2048 -alias box -keystore box.jks -dname "CN=ServiceNow Box JWT Test"

# キーストアからPEM証明書をエクスポートする（キーストアのパスワードを入力する）
keytool -exportcert -rfc -alias box -keystore box.jks > box.cer

# 証明書をRSA公開キーに変換する
openssl x509 -inform pem -in box.cer -pubkey -noout > box.pub
```

Box側の準備として、Box開発者コンソールで[JWT認証アプリ](https://ja.developer.box.com/guides/authentication/jwt/)を以下の設定で作成します：
- アプリ名：<任意の名前>（例：ServiceNowサーバ認証（JWT））
- 「構成」タブでのアクセスレベルとスコープ：アプリの要件に応じますが、この記事で行うテストのためにデフォルトの設定を変更しません。
- 「構成」タブで「公開キーの追加と管理」で「公開キーを追加」ボタンを押下し、生成した`box.pub`の内容を貼り付けます。

![公開キーを追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/7ebf0f91-ac92-a3f5-23b6-087f475be0a3.png)

サーバ認証アプリの場合は、Box管理者による承認が必要で、設定後「承認」タブで承認を依頼します。管理者が承認したら、アプリのサービスアカウントが生成され、「一般設定」タブでサービスアカウントのメールアドレス（Service Account ID）を確認できます。

アプリ作成後、「構成」タブでクライアントIDとクライアントシークレットが表示されます。これらをServiceNowのJWTプロバイダーとアプリケーションレジストリを作成する際に利用します。

### JWTに関するレコードを作成

まず、ServiceNowでX.509証明書の新規レコードを以下のパラメータで作成します：
- 名前：<任意の名前>（例：Boxサーバ認証（JWT)キーストア）
- タイプ：Javaキーストア
- キーストアパスワード：コマンドラインでキーストアを作成した際に設定したパスワード

レコードを保存する前に、生成したキーストアファイル（`box.jks`）をレコードに添付する必要があります。

![X.509証明書を作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/56fdce41-9bcb-a7c7-d207-784c97466753.png)

:::note warn 
キーストアファイルがアップロードできない場合は、mime-typeのチェックを無効化する必要があるかもしれませんので、[ServiceNowガイド](https://docs.servicenow.com/csh?topicname=upload-java-keystore-certificate-to-servicenow-instance.html&version=latest)で確認してください。
:::

次に、JWTキーの新規レコードを以下のパラメータで作成します：
- 名前：<任意の名前>（例：Boxサーバ認証（JWT）キー）
- 署名キーストア：以前作ったキーストア（例：Boxサーバ人方（JWT）キーストア）
- 署名キー：コマンドラインでキーストアを作成した際に設定したパスワード

:::note warn
[ServiceNowガイド](https://developer.servicenow.com/blog.do?p=/post/integrating-servicenow-to-box-with-jwt/)でのStep 4.2で「the Key Id is the alias you used when creating the keystore」が書いてありますが、「キーId」を設定するとエラーが発生しましたので、「キーId」を空で設定します。
:::

![JWTキーを作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/66764132-4477-120e-b1e6-5ac5c89a7e59.png)

次に、JWTプロバイダーの新規レコードを以下のパラメータで作成します：
- 名前：<任意の名前>（例：Boxサーバ認証（JWT）プロバイダー）
- 署名構成：以前作ったキー（例：Boxサーバ認証（JWT）キー）

レコードを保存すると、標準要求を設定する表が表示されて、以下のパラメータで設定します：
- aud: https://api.box.com/oauth2/token
- iss: BoxカスタムアプリのクライアントID
- sub: BoxエンタープライズID
- box_sub_type: enterprise

:::note warn
サービスアカウントではなく、特定のユーザーとして操作をする場合、box_sub_typeの値を「user」にし、subの値をユーザーIDにします。
:::

![JWTプロバイダー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/96efcef6-b6cf-65f4-39d3-9083d75d7364.png)

### アプリケーションレジストリを作成

次に、以下の設定でServiceNow上のアプリケーションレジストリ（「サードパーティ OAuth プロバイダーに接続」）を作成します：
- 名前：<任意の名前>（例：Boxサーバー認証（JWT））
- クライアントIDとクライアントシークレット：Box上でJWT認証アプリの作成時に保存しておいたものを利用します
- デフォルトの権限許可タイプ：JWTベアラー
- トークンURL：https://api.box.com/oauth2/token

:::note warn
[ServiceNowガイド](https://developer.servicenow.com/blog.do?p=/post/integrating-servicenow-to-box-with-jwt/#:~:text=In%20the%20OAuth%20Entity%20Scopes%20related%20list%20(of%20the%20Application%20Registry%2C%20not%20the%20Profile%20from%20immediately%20above)%2C%20you%20will%20need%20to%20specify%20every%20scope%20that%20you%20are%20requesting%20via%20this%20integration.)では、OAuthスコープを追加することが必要だと書いてありますが、テストしたところそれは不要です。
ここでスコープ1つ（例えば、`root_readwrite`）を設定すると問題なさそうですが、2つ（例えば、`root_readwrite`と`manage_app_users`）以上を設定すれば、2つ目以降は適用されません。
一方、ここでスコープを設定しなかったら、Box開発者コンソールで設定したスコープは全て適用されます。
:::

![サーバ認証（JWT）アプリケーションレジストリを作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/e34814e0-3d45-cd61-6192-da67c069be41.png)


レコードを保存すると、次の注意メッセージが表示されます：

![エンティティプロファイルメッセージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/e1018e95-1149-ee90-cd22-e77d881ca58a.png)

エンティティプロファイルとJWTプロバイダーを紐づくには、「エンティティプロファイル」で自動的に生成されたプロファイル（例：Boxサーバ認証（JWT）default_profile）を押下し、JWTプロバイダーを設定します。設定する値は以前作ったプロバイダーです。

![JWTプロバイダーを設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/5d086baf-1fa3-e039-bcf7-97ab325d836e.png)

これでサーバ認証（JWT）の設定が完了します。

# 疎通確認

Boxと正しく接続できているか確認するには、ServiceNowのRESTメッセージで疎通を確認します。

以下の設定で新規RESTメッセージレコードを作成します：
- 名前：<任意の名前>（例：Box認証テスト）
- REST エンドポイント：https://api.box.com/2.0/users/me
- 認証タイプ：OAuth 2.0
- OAuth プロファイル：作られたプロファイルを選択します（例：Boxユーザー認証 default_profile、Boxサーバ認証（CCG） default_profile、Boxサーバ認証（JWT） default_profile）

レコードを保存すると、「関連リンク」セクションで「OAuth トークンの取得」リンクが表示されます。選択した認証方法によって、トークンの取得方法が変わります。

ユーザー認証の場合は、以下のように接続を許可する画面が表示されます。

![Box接続許可.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/833cdfbb-9967-f8dc-8945-0ff5451b3f26.png)

サーバ認証の場合は、自動的に認証されますので許可が不要です。認証が成功したら、以下の確認画面が表示されます。

![サーバ認証成功.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/53a0cecd-f34f-e5fa-d0f7-391c96c4e39b.png)

トークが取得できたら、RESTメッセージ画面の下にある「RESTメッセージ関数」の「Default GET」関数をアクセスし、「関連リンク」セクションの「テスト」を押下します。
正しく接続した場合は、リクエストの応答にユーザーの詳細（IDや名前など）が記載されます。サーバ認証の場合は、サービスアカウントの詳細が出ます。

![RESTメッセージテスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895687/c802b34c-6f92-e1e6-a53e-7b71fb0e471a.png)

# まとめ

この記事では、BoxとServiceNowを連携する際に使われる認証方法について説明しました。

各方法の設定時間や対象ユースケースは異なります。たとえば、ユーザー認証は簡単に設定できますが、バッチ処理には向いていません。そのため、使用目的に応じて適切な方法を選択することが重要です。

ServiceNowとBoxが接続されることで、両方のプラットフォームを活用してITプロセス関連のコンテンツ管理を改善することが期待されます。