アンチパターンから学ぶ 外部APIの実行

目次

はじめに

kintoneのカスタマイズでは、外部のWeb APIを実行し、情報を取得したり外部サービスにデータを送信したりすることがあります。
たとえば、外部の為替レートAPIから最新のレートを取得したり、チャットサービスに通知を送信したりするケースです。

外部APIの実行には、いくつかの実装方法があります。
代表的なものは、ブラウザーのFetch API、kintone.proxy()kintone.plugin.app.proxy()の3つです。
どれを使うかによって、動作の安定性や認証情報の安全性が変わります。

この記事では、外部APIの実行について、2部構成でアンチパターンと推奨される実装方法を解説します。

  • 1. Fetch APIとkintone.proxy()
    Fetch APIで外部APIを直接呼び出すアプローチのリスク(CORS制約)と、kintone.proxy()による解決を解説します。
  • 2. kintone.proxy()kintone.plugin.app.proxy()
    認証情報をコードに直接書くアプローチのリスク(認証情報の漏えい)と、kintone.plugin.app.proxy()による解決を解説します。

既存のカスタマイズのリスク確認や、新たに実装する際の参考にしてください。

今回紹介するAPI

API 概要
kintone.proxy() 外部のAPIを実行
kintone.plugin.app.proxy() プラグインから外部のAPIを実行

1. Fetch APIとkintone.proxy()

まずは、外部APIを呼び出す基本的な方法として、Fetch APIとkintone.proxy()を比較します。
ここでは、架空の外部の為替レートAPIから最新のレートを取得する処理を例にします。

アンチパターン:Fetch APIによる外部APIの呼び出し

外部APIを呼び出す方法として、ブラウザーのFetch APIで直接リクエストするパターンがあります。
ただし、ブラウザーからの直接リクエストはCORS(クロスオリジン)制約の対象となります。

warning
注意

以下のコードはkintone.proxy()を使った実装に置き換えることが推奨される書き方です。
新規のカスタマイズでは、後述するkintone.proxy()を使用してください。

1
2
3
4
5
6
7
8
9
// 非推奨: 外部APIへのFetch APIによる直接リクエストはCORS制約により失敗する可能性があります
(async () => {
  'use strict';

  // ブラウザーから外部APIへ直接リクエストする
  const resp = await fetch('https://api.example.com/rates?base=USD');
  const data = await resp.json();
  console.log(data);
})();

このアプローチには以下のリスクがあります。

リスク 説明
CORS制約で失敗する場合がある ブラウザーからの直接リクエストは同一オリジンポリシーの対象です。
呼び出し先のサービスがCORSを許可していない場合、リクエストがブロックされてレスポンスを受け取れません。
今はリクエストが成功していたとしても、Webサービス側のセキュリティポリシーの変更である日突然CORSを許可しないように設定されるリスクがあります。
CORS制約回避で開発/運用工数が増える CORS制約を回避するには、リクエストを中継するプロキシサーバーを用意する必要があります。
AWSやiPaaSといったサービスがこれにあたります。
外部APIの実行がkintoneだけで完結せず、サーバーの構築や保守のコストが発生します。

推奨される実装方法:kintone.proxy()による外部APIの呼び出し

kintone.proxy()を使用することで、CORS制約を回避して外部APIを呼び出せます。
リクエストがブラウザーからではなくkintoneのサーバーを経由して送信されるため、同一オリジンポリシーの影響を受けません。
自分でCORS制約を回避するためのプロキシサーバーを用意する必要がなくなります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
(async () => {
  'use strict';

  // kintoneのサーバーを経由してリクエストするため、CORS制約を受けない
  const [body, status] = await kintone.proxy(
    'https://api.example.com/rates?base=USD',
    'GET',
    {},
    {}
  );

  // レスポンスボディは文字列で返るため、JSONに変換する
  const data = JSON.parse(body);
  console.log(status, data);
})();

Fetch APIによる外部APIの呼び出しと比較して、以下の点が改善されます。

改善点 説明
CORS制約を回避できる kintoneのサーバーを経由してリクエストするため、ブラウザーの同一オリジンポリシーの影響を受けません。
プロキシサーバーが不要 CORS制約を回避するためのプロキシサーバーを用意する必要がありません。
kintoneのカスタマイズだけで外部APIの実行が完結し、プロキシサーバーの構築や保守のコストが発生しません。
warning
注意

認証情報が不要な公開APIなら、kintone.proxy()で手軽に呼び出せます。
一方、APIキーやトークンなどの認証情報を必要とするAPIでは、実装方法によっては認証情報の漏えいにつながるリスクがあります。
認証情報を扱う場合は、後述のセクション2を参照してください。

kintone.proxy()のAPIドキュメントは、以下を参照してください。

外部のAPIを実行する

2. kintone.proxy()とkintone.plugin.app.proxy()

次に、認証情報が必要な外部APIを呼び出すケースを考えます。
ここでは、APIキーをリクエストヘッダーに付与して外部APIから情報を取得する処理を例にします。

アンチパターン:認証情報をフロントエンドのコードに直接書く

kintone.proxy()のリクエストヘッダーやリクエストボディに、APIキーやトークンを直接書くパターンがあります。

warning
注意

以下のコードはkintone.plugin.app.proxy()を使った実装に置き換えることが推奨される書き方です。
認証情報を扱う新規のカスタマイズでは、プラグインとして実装し、kintone.plugin.app.proxy()を使用してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 非推奨: 認証情報をコードに直接書くと、ブラウザーから読み取られるリスクがあります
(async () => {
  'use strict';

  // APIキーがJavaScriptに含まれるため、第三者に読み取られるリスクがある
  const [body, status] = await kintone.proxy(
    'https://api.example.com/data',
    'GET',
    {Authorization: 'Bearer xxxxxxxxxxxxxxxx'},
    {}
  );

  console.log(status, JSON.parse(body));
})();

このアプローチには以下のリスクがあります。

リスク 説明
認証情報が漏えいする フロントエンドのJavaScriptはブラウザーに配信されるため、開発者ツールやソースの表示で誰でも内容を確認できます。
コードに書いた認証情報も読み取られ、第三者にAPIを悪用されるリスクがあります。
warning
注意

同様に、認証情報の保存先として localStorage・sessionStorage・document.cookie を使う方法も推奨しません。
いずれもJavaScriptからアクセスが可能なため、認証情報が漏えいするリスクがあります。
JavaScriptファイルへの直書きと同様に、フロントエンド側への認証情報の保存は避けてください。

推奨される実装方法:kintone.plugin.app.proxy()による外部APIの呼び出し

kintone.plugin.app.proxy()は、プラグイン内でのみ利用できるAPIです。
このAPIを使用することで、認証情報をコードに含めることなく外部APIを呼び出せます。
認証情報は、あらかじめプラグインの設定としてkintoneのサーバー側へ保存します。
保存した認証情報は、リクエストの送信時にサーバー側で自動付与されます。
そのため、フロントエンドのJavaScriptには認証情報が現れず、漏えいを防げます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 認証情報はプラグインの設定としてサーバー側に保存され、リクエスト時に自動で付与される
// kintone.$PLUGIN_ID で実行中のプラグインIDを取得し、引数として渡す
(async (pluginId) => {
  'use strict';

  const [body, status] = await kintone.plugin.app.proxy(
    pluginId,
    'https://api.example.com/data',
    'GET',
    {},
    {}
  );

  console.log(status, JSON.parse(body));
})(kintone.$PLUGIN_ID);

kintone.$PLUGIN_IDの使い方は、 プラグインIDの参照例 を参照してください。

認証情報をコードに直接書く方法と比較して、以下の点が改善されます。

改善点 説明
認証情報が漏えいしにくい 認証情報はプラグインの設定としてサーバー側に保存され、リクエスト時に自動で付与されます。
フロントエンドのJavaScriptには認証情報が含まれないため、ブラウザーから読み取られません。

kintone.plugin.app.proxy()を使うには、カスタマイズをプラグインとして作成し、認証情報を保存するしくみを実装する必要があります。
プラグインの作成手順や、認証情報の保存と隠蔽の方法は、以下の記事を参照してください。

kintone.plugin.app.proxy()のAPIドキュメントは、以下を参照してください。

プラグインから外部APIを実行する

実装時に押さえておきたいこと

外部APIの実行において、共通して押さえておきたい点を案内します。
事前に把握しておくことで、実装後のトラブルを未然に防げます。

レスポンスと制限

kintone.proxy()kintone.plugin.app.proxy()には、共通して以下の制限があります。

  • レスポンスボディは文字列で返るため、JSONを扱う場合はJSON.parse()で変換します。
  • レスポンスボディの上限は10MBで、上限を超えるとエラーになります。
  • 画像などのバイナリデータは取得できません。
  • 自己署名証明書を使ったサーバーとは通信できません。

同一ドメインへのリクエスト

自分のkintone環境のREST APIを呼び出す場合は、kintone.proxy()ではなくkintone.api()を使用します。
kintone.proxy()でも同一ドメインのkintone REST APIを呼び出せますが、すべてのkintone環境から自由にアクセスできる経路を開くことになるため、セキュリティの観点から推奨されていません。

非同期処理の活用

今回紹介したAPIはすべて非同期なAPIです。
async/awaitを使用して順序どおりに処理してください。
詳しくは次のページを参照してください。

モバイル版での利用について

今回紹介したAPIは、モバイル版でも利用できます。
kintone.proxy()kintone.plugin.app.proxy()はどちらもPC版・モバイル版で同じコードが動作します。

PC版 モバイル版
kintone.proxy() kintone.proxy()
kintone.plugin.app.proxy() kintone.plugin.app.proxy()

まとめ

  • kintone.proxy()で、CORS制約を回避し、プロキシサーバーなしで外部APIを呼び出せます。
  • 認証情報が必要なAPIでは、kintone.plugin.app.proxy()で認証情報をコードに含めることなく呼び出せます。
  • 同一ドメインのkintone REST APIには、kintone.api()を使用します。

外部APIの実行では、用途に応じてこれらのAPIを使い分けることで、安全で保守しやすいカスタマイズを実現できます。
特に認証情報を扱う場合は、漏えいを防ぐためにkintone.plugin.app.proxy()の利用を検討してください。

information

このTipsは、2026年6月版kintoneで動作を確認しています。

公式コミュニティ

kintone開発者同士で質問や知見を共有し、学び合うことができます。