Node.jsのAPIクライアントを作成する

Stay hungry. Stay foolish. Your time is limited, so don't waste it living someone else's life.

Node.jsのAPIクライアントを作成する

はじめに

 当記事は、Node.jsのAPIクライアントからJWT付きのリクエストを送信しJWT検証ポリシーを実装したMuleのAPIを呼び出す環境を作成し動作検証する手順について説明している。

目次

下記の手順で動作確認用の環境を作成し動作確認する。

  1. JWT署名用証明書を作成する
  2. Node.jsのAPIクライアントを準備する
  3. MuleのAPIを準備する
  4. JWT検証ポリシーを設定する
  5. 動作を確認する

手順

1.JWT署名用証明書を作成する

 APIクライアントのJWTの生成に利用するJWT署名用証明書と、APIでJWTが有効か検証するためのJWT検証ポリシーで利用するJWT署名検証用公開鍵を作成する。
 前提として環境には、JDK1.8とOpensslがインストールされている必要がある。

KeytoolでJKS形式のJWT署名用証明書を作成する。

$ keytool -genkeypair -keystore jwt_client_dev.jks -dname "CN=api.localhost.com, OU=Mulesoft Dev, O=Localhost Ltd., L=minato-ku, ST=Tokyo, C=JP" -keypass password -storepass password -keyalg RSA -sigalg SHA1withRSA -keysize 2048 -alias jwt_client_dev -validity 36524

JKS形式からPKCS12形式に変換する。
このファイルをAPIクライアントで利用する。

$ keytool -importkeystore -srcstorepass password -storepass password -srckeystore jwt_client_dev.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore jwt_client_dev.p12

JWT署名検証用の公開鍵を作成する。
このファイルをJWT検証ポリシーで利用する。

$ keytool -exportcert -keystore jwt_client_dev.jks -alias jwt_client_dev -file cert_dev.der -storepass password
$ openssl x509 -inform DER -outform PEM -in cert_dev.der -out cert_dev.pem
$ openssl x509 -inform PEM -in cert_dev.pem -pubkey -noout > jwt_client_dev_public.pem

以上で、署名用証明書と署名検証用の証明書の準備は完了である。

2.Node.jsのAPIクライアントを準備する

 JWTの生成しAPIと通信するためのNode.jsのAPIクライアントを準備する。
 前提として、開発環境にはNode.jsがインストールされている必要がある。

Node.jsのプロジェクトを作成する。

npm init -y

APIクライアントに必要なライブラリをインストールする。
証明書ファイルを操作するライブラリをインストールする。

npm install node-forge

JWT生成用ライブラリをインストールする。

npm install jose

index.jsに下記のプログラムをコピペする。
※hostnameは、APIをRuntime Managerにデプロイした後に発行されるURLを設定する。

var forge = require('node-forge')
var fs = require('fs')
const jose = require('jose')
const https = require('https');

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

if (require.main === module) {
    main();
  }

// HTTPリクエスト
async function main () {
    const token = await generateJWT()
    const options = {
        hostname: 'account-app-6ucdsr.5sc6y6-3.usa-e2.cloudhub.io',
        port: 443,
        path: '/api/account/123',
        method: 'GET',
        json: true,
        headers: {
            'Content-Type': 'application/json; charset=UTF-8',
            'jwt': token
          }
    };
    const req = https.request(options, (res) => {
        console.log('statusCode:', res.statusCode);
        console.log('headers:', res.headers);
        
        res.on('data', (d) => {
                process.stdout.write(d);
            });
        });

    req.on('error', (e) => {
        console.error(e);
        });
    req.end();
}

// JWT生成処理
async function generateJWT(){

    // PKCS12形式のJWT署名用証明書ファイルから秘密鍵の取得
    const keyFile = fs.readFileSync('jwt_client_dev.p12')
    const keyBase64 = keyFile.toString('base64')
    const p12Der = forge.util.decode64(keyBase64)
    const p12Asn1 = forge.asn1.fromDer(p12Der)
    const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, 'password')
    const privateKey = p12.getBags({ bagType: forge.pki.oids.pkcs8ShroudedKeyBag })[forge.pki.oids.pkcs8ShroudedKeyBag][0].key
    const rsaPrivateKey = forge.pki.privateKeyToAsn1(privateKey)
    const privateKeyInfo = forge.pki.wrapRsaPrivateKey(rsaPrivateKey)
    const pemPrivate = forge.pki.privateKeyInfoToPem(privateKeyInfo)

    // JWT生成
    const header = {
        "alg":"RS256",
        "typ":"jwt"
    }
    const issat = Math.floor(new Date().getTime()/1000)
    const exp = issat + (3*60)
    const secret = await jose.importPKCS8(pemPrivate, "RS256")
    console.log(secret)
    const jwt = await new jose.SignJWT({})
    .setProtectedHeader(header)
    .setSubject("subject")
    .setIssuer("client.my.salesforce.com")
    .setAudience("api.localhost.com")
    .setNotBefore(issat)
    .setIssuedAt(issat)
    .setExpirationTime(exp)
    .sign(secret)
    return jwt
}

以上で、APIクライアントの準備は完了である。

3.MuleのAPIを準備する

 APIクライアントから呼び出されるMuleのAPIを準備する。
下記の手順でAPIを準備する。

  1. MuleSoftのトライアルアカウントを作成する
  2. Design Centerを選択し、API仕様のプロジェクトを作成する
  3. エディタに下記のAPI仕様(RAML)をコピペする。
  4. Exchangeに公開する
  5. API ManagerでBasic EndpointのAPIインスタンスを作成する
  6. Anypoint StudioでExchangeからAPIをダウンロードする
  7. フローを自動生成する
  8. Auto Discoveryエレメントを追加する
  9. Runtime Managerにデプロイする
#%RAML 1.0
baseUri: https://api.localhost.com/
title: Account API
version: v1

/account/{ID}:
  get:
    responses:
      200:
        body:
          application/json:
            example: |
              {
                "Id" : "0012x000009umi3AAA",
                "Name" : "AccountTree1",
                "CleanStatus" : "Pending",
                "Website" : "www.salesforce2.com",
                "Industry" : "Banking",
                "NumberOfEmployees" : 100,
                "OwnerId" : "0052x000002EsZBAA0",
                "Phone" : "1234567890",
                "PhotoUrl" : "/services/images/photo/0012x000009umi3AAA",
                "SystemModstamp" : "2020-07-23T02:57:09.000+0000",
                "CreatedById" : "0052x000002EsZBAA0",
                "CreatedDate" : "2020-07-23T02:57:09.000+0000"
              }

以上で、APIの準備は完了である。

4.JWT検証ポリシーを設定する

 API ManagerでAPIインスタンスにJWT検証ポリシーを設定する。
設定値は以下の通り。

No.項目名設定値
1Origin of the JWTCustom Expression
2JWT Signing MethodRSA
3JWT Signing Key Length256
4JWT Key originText
5JWT Key※JWT署名検証用の公開鍵をコピペする
6Skip Client Id ValidationCheck
7Validate Audience ClaimCheck
8Audience Claim MandatoryCheck
9Audience Claim Valuesapi.localhost.com
10Expiration Claim MandatoryCheck
11Not Before Claim MandatoryCheck

以上で、JWT検証ポリシーの設定は以上である。

5.動作を確認する

 Node.jsのAPIクライアントからJWT付きのリクエストを送信し、APIでJWTが有効であればAPIクライアントが正常のレスポンスを受け取ることを確認する。
下記のコマンドを実行してMule APIにリクエストを送信する。

node index.js

下記のようにレスポンスが正しくターミナルに表示されることが確認する。

以上で動作確認を完了する。

さいごに

 いかがだったでしょうか?
 Node.jsのAPIクライアントからJWT付きリクエストを送信して、正しくレスポンスを受け取ることができました。
 ぜひ、試してみてください。では、

 

コメントを残す