API 保護

開発者として API を保護する場合には、承認に重点を置く必要があります。 アプリケーションからリソースの API を呼び出すには、そのアプリケーションがアプリケーション承認を取得している必要があります。 リソース自体が承認を執行する必要があるのです。 この記事では、ゼロ トラストの目標を達成するために、登録、アクセス許可と同意の定義、アクセスの適用を通じて、API を保護するためのベスト プラクティスを学習します。

保護された API を登録する

Microsoft Entra ID で API を保護する (Microsoft Entra ID) には、まず API を登録します。これにより、登録した API を管理することができます。 Microsoft Entra ID では、API とは、別のアプリケーションが承認を受けてアクセスすることのできる、リソースまたは API として定義される所定のアプリケーション登録設定を持つアプリケーションです。 Microsoft Entra 管理センターである Microsoft Identity Developer においては、 アプリケーション登録 とは、基幹業務 API 、または Microsoft Entra ID の保護対象である API を持つ SaaS プロバイダーのサービスとしてテナント内に存在する API を指します。

登録時に、呼び出しアプリケーションで API を参照する方法と、その委任アプリケーションのアクセス許可を定義します。 アプリケーション登録は、クライアント アプリケーションと API の両方を持つソリューションを対象とする場合もあります。 ただし、この記事では、スタンドアロン リソースで API を公開するシナリオについて説明します。

通常、API が認証を実行したり、承認を直接要求することはありません。 API は、呼び出しアプリで提示されるトークンを検証します。 API には対話型のサインインがないため、リダイレクト URI やアプリケーションの種類などの設定を登録する必要はありません。 API は、Microsoft Entra ID とのやり取りによってではなく、それらの API を呼び出しているアプリケーションからトークンを取得します。 Web API の場合は、承認に OAuth2 アクセス トークンを使用します 。 Web API は、ベアラー トークンを検証して呼び出し元を承認します。 ID トークンをアクセス許可の証明として受け入れないでください。

既定では、Microsoft Entra ID はすべての新しいアプリケーション登録の API アクセス許可に User.Read を追加します。 ほとんどの Web API ではこのアクセス許可を削除します。 Microsoft Entra ID は、API が別の API を呼び出す場合にのみ API アクセス許可を要求します。 API が別の API を呼び出すことがない場合は、API を登録するときに User.Read アクセス許可を削除すること。

API にアクセスする必要があるクライアント アプリが API を呼び出すアクセス許可を求めるアプリケーション ID URI とも呼ばれる API の一意識別子が必要です。 アプリケーション ID URI は、すべての Microsoft Entra テナントに対して一意である必要があります。 api://<clientId> (ポータルの既定の提案) を使用できます。ここでは、<clientId> が登録されている API のアプリケーション ID となります。

API を呼び出す開発者にとってわかりやすい名前を付けるために、API のアドレスをアプリケーション ID URI として使用できます。 たとえば、https://API.yourdomain.com を使用する場合には、yourdomain.com が Microsoft Entra テナント内の構成済みパブリッシャードメインである必要があります。 Microsoft では、そのアドレスを API の一意識別子として使用できるように、あなたがドメイン の所有者であるかどうかを検証します。 このアドレスにコードを記述する必要はありません。 API はどこにあっても構いませんが、API の HTTPS アドレスをアプリケーション ID URI として使用することをお勧めします。

最小の特権を持つ委任されたアクセス許可を定義する

API がユーザーを持つアプリケーションによって呼び出される場合は、少なくとも 1 つの委任されたアクセス許可を定義する必要があります (APIを公開するアプリケーション登録にスコープを追加するを参照してください)。

組織のデータ ストアへのアクセスを提供する API は、そのデータへのアクセスをねらう攻撃者の注目を集める場合があります。 委任されたアクセス許可を 1 つだけ設定するのではなく、最小限の特権アクセスのゼロ トラスト原則を念頭に置いてアクセス許可を設計してください。 すべてのクライアント アプリケーションが完全な特権アクセスからスタートしていると、後で最小特権モデルを適用するのは困難な場合があります。

多くの場合、開発者は、"ユーザーとしてのアクセス" や "ユーザーなりすまし" などの単一のアクセス許可を使用しがちです (これらは技術的には不正確な用語ですが、一般的に使われる表現です)。 このような単一のアクセス許可では、API への完全な特権アクセスのみが許可されます。

アプリケーションがセキュリティ侵害に対して脆弱にならないように、または意図しないタスクの実行に使用されないように、最小限の特権スコープを宣言してください。 API アクセス許可内に複数のスコープを定義すること。 たとえば、スコープをデータの読み取りと更新から分離し、読み取り専用のアクセス許可を提供することを検討してください。 "書き込み アクセス" には、作成、更新、削除の操作権限が含まれます。 クライアントが、データを読み取るだけのために書き込みアクセス許可を要求されることがあってはなりません。

機密データを取り扱う API の場合は、"標準" と "フル" のアクセス許可の使い分けを検討しましょう。 機密性の高いプロパティについては、標準アクセス許可でアクセスを許可しないように制限を設定します (たとえば、Resource.Read など)。 次に、プロパティや機密情報を返す "フル" アクセス許可を実装します (たとえば、Resource.ReadFull など)。

要求するアクセス許可を評価して、常にジョブの完了のために必要最小限の特権セットをのみを求めるようにすること。 必要以上に高い特権のアクセス許可を要求しないでください。 コア シナリオごとに個別にアクセス許可を作成するようにすること。 このアプローチの良い例については、 Microsoft Graph のアクセス許可リファレンスを参照してください。 ニーズに応じて、必要なタイプの複数のアクセス許可を配置して使用します。

スコープ定義の一部として、特定のスコープで実行できる操作の範囲に管理者の同意を必要とするかどうかを決定します。

API デザイナーは、どのようなスコープをユーザー同意の要求のみで安全に管理できるかについてのガイダンスを提供することができます。 いっぽう、テナント管理者は、すべてのアクセス許可に管理者の同意を必要とするようにテナントを構成することができます。 管理者の同意が必要なスコープを定義した場合、そのアクセス許可には常に管理者の同意が必要です。

ユーザーの同意のみでよいか、或いは管理者の同意を必要とすべきかを判断するには、主に次の 2 つの事項を考慮してください。

  1. そのアクセス許可によって可能となる操作の範囲が複数のユーザーに影響を与えるものであるかどうか。 ユーザーが自分自身の情報のみにアクセスできるアプリケーションを選択できるアクセル許可である場合は、ユーザーの同意は適しているといえます。 たとえば、使用したい電子メール アプリケーションを選択する場合などは、ユーザーの同意のみで良いでしょう。 逆に、アクセス許可によって可能となる操作が複数のユーザーに関わるものである場合 (たとえば、他のユーザーの完全なユーザー プロファイルを閲覧できる場合など)は、そのようなアクセス許可には管理者の同意を必要とするように定義してください。

  2. そのアクセス許可によって可能となる操作の範囲が広範なスコープであるかどうか。 広範なスコープとは、例えば、そのアクセス許可によって、アプリケーションがテナント内のすべてを変更したり、元に戻せない可能性のある操作を行うことが可能になる場合です。 広範なスコープが関わるアクセス許可については、ユーザーの同意ではなく管理者の同意を必要とすること。

安全のため、判断が難しい場合にはすべて管理者の同意を必要とするようにしてください。 同意した場合の結果を明確かつ簡潔に、アクセス許可文字列に記述してください。 その文字列を読むユーザーにAPI や製品に関する知識がないとの前提で記述を行うこと。

アクセス許可の意味が代わってしまうような形で、既存のアクセス許可に API を追加しないこと。 既存のアクセス許可をオーバーロードすると、クライアントがこれまでにそのアクセス許可に同意を与えた意義が薄められます。

アプリケーションのアクセス許可を定義する

非ユーザー アプリケーションを構築する場合、ユーザー名とパスワード、または多要素認証 (MFA) の入力を求めることができるユーザーはいません。 非ユーザー アプリケーション (ワークロード、サービス、デーモンなど) で API を呼び出す場合、API に対してアプリケーションのアクセス許可を定義する必要があります。 アプリケーションのアクセス許可を定義する場合、スコープを使用する代わりにアプリケーション ロールを使用します。

委任されたアクセス許可と同様に、API を呼び出すワークロードが最小限の特権アクセスに従い、ゼロ トラストの原則に沿うことができるように、詳細なアプリケーションのアクセス許可を提供します。 1 つのアプリケーション ロール (アプリケーション アクセス許可) と 1 つのスコープ (委任されたアクセス許可) のみを発行したり、すべての操作をすべてのクライアントに公開したりしないでください。

次のコード例に示すように、ワークロードはクライアント認証情報を使用して認証を行い、.default スコープを使用してトークンを要求します。

// With client credentials flows the scopes is ALWAYS of the shape "resource/.default", as the 
// application permissions need to be set statically (in the portal or by PowerShell), 
// and then granted by a tenant administrator
string[] scopes = new string[] { "https://kkaad.onmicrosoft.com/webapi/.default" };
 
AuthenticationResult result = null;
try
{
  result = await app.AcquireTokenForClient(scopes)
    .ExecuteAsync();
  Console.WriteLine("Token acquired \n");
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
  // Invalid scope. The scope has to be of the form "https://resourceurl/.default"
  // Mitigation: change the scope to be as expected
  Console.WriteLine("Scope provided is not supported");
}

アプリケーションを操作するユーザーがいない場合や、そのアプリケーション アクセス許可により広範な操作が可能になる場合には、管理者の同意を必要とするようにしてください。

アクセスを適用する

呼び出しアプリケーションが HTTPS 要求のAuthorization ヘッダーでベアラー トークンとして提供するアクセス トークンを検証および解釈することで、API にアクセスが適用されるようにします。 次のセクションで説明するように、トークンを検証し、メタデータの更新を管理し、スコープとロールを適用することで、アクセスを執行できます。

トークンを検証する

API がトークンを受け取ったら、そのトークンを検証する必要があります。 検証により、そのトークンが適切な発行者により提供されており、タンパリングや改変されていないことを確認します。 ID トークンのように Microsoft Entra ID からトークンを直接受け取ることはないため、署名をチェックします。 API がネットワーク上の信頼されていないソースからトークンを受け取った場合には、署名の検証を行います。

JSON Web トークン署名検証プロセスには脆弱性があることが知られているため、適切に維持され確立されている標準トークン検証ライブラリを使用します。 認証ライブラリ (Microsoft.Identity.Web など) で適切な手順を使用し、既知の脆弱性を軽減します。

必要に応じて、トークンの検証を拡張します。 テナント ID (tid) クレームを使用して、API がトークンを取得できるテナントを制限します。 API を呼び出すことができるアプリケーションをフィルタリングするには、azp クレームと appid クレームを使用します。 オブジェクト ID (oid) クレームを使用すると、アクセス範囲を個々のユーザーレベルに絞り込むことができます。

メタデータの更新を管理する

トークン検証ライブラリが必要なメタデータを効果的に管理しているかどうかを常に確認してください。 この場合、メタデータは、Microsoft が Microsoft Entra トークンの署名に使用する公開キー (秘密キーのペア) です。 ライブラリでこれらのトークンを検証する場合、よく知られているインターネット アドレスから公開署名キーの一覧を取得します。 ホスティング環境からこれらのキーを取得できる適切なタイミングを確認してください。

たとえば、古いライブラリは、24 時間ごとにこれらの公開署名キーを更新するようにハードコーディングされている場合があります。 Microsoft Entra ID でこれらのキーをすばやくローテーションする必要があり、ダウンロードしたキーに新しくローテーションされたキーが含まれないタイミングを検討してください。 API は、メタデータの更新サイクルを待つ間、最大で 1 日オフラインになる可能性があります。 メタデータを適切に取得できるように、所定のメタデータ更新ガイダンスを参照してください。 ライブラリを使用している場合は、適切なタイミングでそのメタデータが処理されていることを確認します。

スコープとロールを適用する

トークンを検証した後、API ではトークンの要求に注目し、そのしくみを決定します。

委任されたアクセス許可トークンの場合は、API にスコープ (scp) クレームを調べさせ、アプリケーションが何に対して同意を取得しているかを確認させるようにします。 オブジェクト ID (oid) またはサブジェクト キー (sub) クレームを調べて、アプリケーションを動作させているユーザーを確認します。

次に、API にチェックを実行させ、ユーザーが要求された操作へのアクセス許可を持っているかどうかを確認させます。 API でユーザーやグループに割り当てるロールを定義する場合、API はトークンにロールの要求がないか確認し、それに従って動作します。 アプリケーションのアクセス許可トークンにはスコープ (scp) の要求がありません。 代わりに、API でロールの要求を検査し、ワークロードがどのアプリケーションのアクセス許可を受け取ったかを決定します。

API がトークンとスコープを検証し、オブジェクト ID (oid)、サブジェクト キー (sub)、およびロールの要求を処理した後、API は結果を返すことができます。

次のステップ