OAuth Providerの有効期限等の動的変更方法

# はじめに

　この記事ではIBM API Connect v10 で提供しているOAuth Providerリソースの基本設定を動的に変更する方法を紹介します。
API Connectでは、OAuth 2.0の仕様をサポートし、認可サーバーとして構成するためのOAuth Provider機能を提供しています。

[IBM Documentation: OAuth Provider overview](https://www.ibm.com/docs/en/api-connect/10.0.5.x_lts?topic=security-oauth-provider-overview)

　この機能では、1つのOAuth Provider定義に対して、アクセストークン等の有効期限を設定することができますが、用途によっては1つの定義を作成し、カタログや、クライアントからの要求内容に応じて動的に設定を変更したい場合があります。この記事ではこのような要件に対応する方法を紹介します。

 　今回は、Kubernetes環境に導入したAPI Connect v10.0.5.6/DataPower v10.5.0.9で検証しています。
  
# 1. OAuth Provider基本動作確認

 OAuth ProviderはAPI Managerのリソースメニューから登録することができます。今回は以下のような設定で登録しています（アクセス・トークンの有効期限は3600秒としています）。有効期限の設定項目では、数値のみが許可されており、プロパティーなどの変数参照（$(variable)）を使った設定はできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403443/b02fd2b5-424c-329b-facf-7c27bb262e36.png)



　別のAPI定義の中で、このリソースを使用してOAuth保護設定して公開することで、OAuthエンドポイントを使用することができます。この操作により公開されたOAuth Providerエンドポイントを呼び出すと、以下のような結果となります。有効期限は上記の設定の通り3600秒になっていることがわかります（expires_inフィールド）。

```
$ curl -ki -u '<client-id>':'<client-secret>' -X POST \
  --url https://rgw.xx.xx.xx.xx/test-org/sandbox/v1/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" \
  -d 'grant_type=authorization_code&scope=scope1&redirect_uri=&code=****'
HTTP/1.1 200 OK

{"token_type":"Bearer","access_token":"****","scope":"scope1","expires_in":3600,"consented_on":1714441157,"refresh_token":"AALn****","refresh_token_expires_in":2682000}

```

# 2. OAuth Provider拡張動作設定

## 2.1. OAuth Providerデフォルト設定のオーバーライド方法

 上記の設計画面で設定した有効期限は、アセンブルでオーバーライドすることができます。APIエディターメニューからアセンブルの編集画面に移動します。アセンブルではOAuth Providerの動作をカスタマイズすることができます。今回は、トークン発行時（/oauth2/token）の有効期限を変更したいので以下の赤枠のOAuthポリシーを変更します。
 
　このポリシーでは、「リテラル・ストリングからの動的OAuth構成」や、「URLからの動的OAuth構成」という設定項目があり、指定の設定フォーマットの直打ちや、外部URL/ローカルファイル等からインポートして動的にオーバーライドすることができます。なお、これらの設定項目でも、プロパティーなどの変数参照（$(variable)）を使った設定はできませんのでご注意ください（変数解決がされず参照エラーとなります）。
 
 ここでは、前者の方法で、OAuth Provider設定値（アクセストークンの有効期限を1800秒）を動的に変更してみます。変更後は「保存」を押下することで、即時変更が反映されます。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403443/afe72831-8580-88a5-c52f-520448857295.png)

```xml
<OAuthProviderSettings><APICAccessTokenTTL>1800</APICAccessTokenTTL></OAuthProviderSettings>
```

実際にOAuth Providerエンドポイントを呼び出すと以下の結果となります。
アクセストークンの有効期限が1800秒に変わることが確認できました。

```
$ curl -ki -u '<client-id>':'<client-secret>' -X POST \
  --url https://rgw.xx.xx.xx.xx.nip.io/test-org/sandbox/v1/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" \
  -d 'grant_type=authorization_code&scope=scope1&redirect_uri=&code=****'
HTTP/1.1 200 OK

{"token_type":"Bearer","access_token":"****","scope":"scope1","expires_in":1800,"consented_on":1714441251,"refresh_token":"****","refresh_token_expires_in":2682000}

```


OAuthポリシーの設定方法については以下に記載がありますので併せてご参照ください。

[IBM Documentation: OAuth](https://www.ibm.com/docs/ja/api-connect/10.0.5.x_lts?topic=policies-oauth)


 ## 2.2. OAuth Providerデフォルト設定の動的変更方法

　上記の設定を活用して、例えば、カタログごとの設定を動的に変更する方法を紹介します。今回はOAuthポリシーの「URLからの動的OAuth構成」設定を使用します。
　ここでは、DataPowerのローカルファイルシステム上のtemporaryディレクトリーの構成ファイル（temporary:///oauth-dynamic-config.config）を指定します。このファイルのデータが2.1.で示したXML形式になっていれば、同様の動作となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403443/33e620a3-ecb7-1816-981d-015e18cf09dd.png)

　上記の構成ファイルを作成するために、OAuthポリシーの直前にGatewayScriptポリシーを設定します。このコードでは、OAuth Providerソースに設定したカタログごとのプロパティー値（accesstokenttl）を取得し、この値を使用してXML形式のデータをファイル出力しています。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403443/ea81a907-5d02-906d-c908-37df2adc38ab.png)


```javascript

# OAuth Providerソースに設定したカタログごとのプロパティー値から値を取得
var ttl = context.get('api.properties.accesstokenttl');

# XML形式の構成データを作成
var xml = "<OAuthProviderSettings><APICAccessTokenTTL>" + ttl + "</APICAccessTokenTTL></OAuthProviderSettings>" ;


# 上記のデータをファイル出力
var fs = require('fs');
var temp_file =  'temporary:///oauth-dynamic-config.config';
var buf = new Buffer(xml);
var emptybuffer = "";
var options = {'file': temp_file,'data': buf, 'TTL': 15};

fs.writeFile(options, function(error) { 
  if(error) {
    console.error(error);
  } else {
    fs.appendFile(temp_file, emptybuffer, function(error) {
      if(error){
        console.error(error);
      } else {
        console.log('appendFile success.');
      }
    });
  }
});
```
　ファイル出力方法については、以下の情報を併せてご参照ください。

[IBM Documentation: fs module](https://www.ibm.com/docs/en/datapower-gateway/10.5.0?topic=apis-fs-module)

　「accesstokenttl」プロパティーについては、ソースタブから以下のようにカタログごとに値を設定することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403443/4d8c7efc-0cc5-127d-ec5d-0c17549f8d4c.png)

```yaml
  properties:
    accesstokenttl:
      value: '1800'
      encoded: false
  catalogs:
    sandbox:
      properties:
        accesstokenttl: '1800'
    test-bank1:
      properties:
        accesstokenttl: '1802'
    test-bank2:
      properties:
        accesstokenttl: '1803'
```




 　この内容でOAuth Providerエンドポイントを呼び出すと以下の結果となります。アクセストークンの有効期限（expires_in）が変更されることが確認できました。

  ```
  curl -ki -u '<client-id>':'<client-secret>' -X POST \
  --url https://rgw.xx.xx.xx.xx.nip.io/test-org/sandbox/v1/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" \
  -d 'grant_type=authorization_code&scope=scope1&redirect_uri=&code=****'
HTTP/1.1 200 OK

{"token_type":"Bearer","access_token":"****","scope":"scope1","expires_in":1800,"consented_on":1714444180,"refresh_token":"****","refresh_token_expires_in":2682000}
  ```

  　ここではプロパティー値から設定しましたが、任意の方法で有効期限情報を設定し、ファイル出力することで様々な要件に対応することができます。


# 注意事項

　ローカルファイル出力する場合はファイル名に注意が必要となります。API Connect（API Gatewayモード）では、以下のドキュメントキャッシュポリシーが設定されています。ファイル名を（temporary:///*.xml）とすると、このポリシーに則ってキャッシュされるため、その後の更新が反映されない可能性があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403443/d8efc1dd-274a-4f2e-19ff-45a621a9b48b.png)


 以上です。