JWTを利用してSalesforceからMuleSoftのAPIを呼び出そう！

# はじめに
　Webアプリケーションの標準仕様となっているJWTを利用して、SalesforceからMuleSoftの公開APIに接続する場合の仕組みや制限事項を調査しました。ざっと、調べた内容を並べたので見にくくてすいません。

# JWTの概要
　JWTの概要は以下の通りです。今回の検証では署名のみの検証パターンで検証しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/71b1b982-1393-cdd8-e28f-e25ff421f738.png)

# 外部サービスの概要（API呼び出しに利用）
　外部サービスの概要は以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/d0911c8f-f18d-ca37-d5d7-8ad2aec3b0fb.png)

# 外部サービスを利用したJWTの制約事項
 外部サービスを利用した場合のJWTの制約事項は以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/b0e4993e-7355-d47f-e04d-41ba9263878b.png)

# Apexを利用したJWTの考慮事項
Apexを利用した場合の考慮事項は以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/8a7472f7-ed7a-a2dd-a37d-ce2e50de33cc.png)


# 署名アルゴリズムの特徴
　認証アルゴリズムの特徴をまとめました。SalesforceではRSAが固定です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/34e7b83d-5ef1-d33b-3b29-ceb629bf5989.png)

## SalesforceとMule間のJWTの署名と検証の仕組み
SalesforceとMuleSoft間の署名と検証の仕組みは以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/041192d6-6ad2-f945-5cc4-c771b59cf923.png)



# 検証までの設定手順
 検証を行うために下記の設定手順を実施します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/76ee5b0e-702e-7abf-8f65-d0dfd13ed59f.png)

# ポリシーと互換性があるPEM公開キーの取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/6d68b46a-a193-7b94-d399-9f7c352f96e3.png)


### キーストアの作成

```
$keytool -genkeypair -keystore keydir/keystore.jks   -dname "CN=localhost, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown"  -keypass password  -storepass password  -keyalg RSA  -sigalg SHA1withRSA  -keysize 2048  -alias mule  -ext SAN=DNS:localhost,IP:127.0.0.1 -validity 9999
```
### 公開鍵と非公開鍵の作成

```
$keytool -importkeystore -srckeystore keydir/keystore.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore keydir/keystore.p12
$openssl pkcs12 -in keydir/keystore.p12 -nokeys -out keydir/cert.pem
$openssl x509 -inform pem -in keydir/cert.pem -pubkey -noout > keydir/public.pem
$openssl pkcs12 -in keydir/keystore.p12 -nodes -nocerts -out keydir/key.pem
```

# SalesforceのJWTトークン
　MuleSoftのログからJWTトークンを取得し、JWT Debuggerで内容を可視化しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/52d4f90f-b980-430c-3134-16848b44c759.png)

# 検証結果（外部サービス）
　アクションコンポーネントのメニューから対象のAPIを設定し配置することで、簡単に呼出しが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/bf3ec377-c135-7d29-0d26-bd3a7844c9c8.png)

# 検証結果（Apex）
　指定ログインの設定も合わせて、JWTトークンを任意の場所に設定することやプライベートクレームを設定もできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/4292b8e1-122e-4e4b-21ac-fa738c43212a.png)

``` MuleCallOut
public class MuleCallOut {

    public static String getCalloutResponseContents(Boolean flg) {
        String url = 'callout:MuleClientA/{uri_parameter}';
        if (flg) {
            url = 'callout:MuleClientB/{uri_parameter}';
        }
        Http h = new Http();
    	HttpRequest req = new HttpRequest();
        req.setHeader('jwt', '{!$Credential.AuthorizationHeaderValue}');
    	req.setEndpoint(url);
    	req.setMethod('GET');

    	// Send the request, and return a response
    	HttpResponse res = h.send(req);
        System.debug('>>> Header.Authorization :: ' + req);
        System.debug('>>> getBody :: ' + res.getBody());
    	return res.getBody();
	}
}
```


# MessageLoggingポリシーを利用したJWTの確認方法
　MessageLoggingポリシーを利用してJWTの内容をログに出力できます。base64でエンコードされていますので、コアのライブラリのメソッドを指定してデコードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76270/693cf7ba-1f7e-7330-4f4b-eb90ea1bb136.png)

```
#[dw::core::Binaries::fromBase64((((attributes.headers["jwt"] as String) splitBy("."))[1]) as String)]
```

# まとめ
　JWTトークンを利用してSalesforceからMuleSoftの公開APIの読み出しを検証しました。
　検証により、JWTの仕組みや制限事項が明確になり、ApexやMule実装に必要処理やキーストアが必要な理由についても理解できたと思います。
　お客様との打ち合わせで、要件に合わせて何ができて何ができないのかトレードオフについて「サラっ」とこたえられるようになったら素敵ですね。
　では！