Web サービス用の OAuth 2.0 On-Behalf-Of 更新トークンをセキュリティで保護する

Azure CLI
Azure DevOps
Azure Functions
Azure Key Vault
Azure Pipelines

Web サービスを開発するときに、OAuth 2.0 On-Behalf-Of (OBO) フローを使用してトークンを取得することが必要になる場合があります。 OBO フローは、アプリケーションがサービスや Web API を呼び出し、それがさらに別のサービスや Web API を呼び出す必要のあるユース ケースで役に立ちます。 OBO により、委任されたユーザー ID とアクセス許可が要求チェーン経由で伝達されます。 アプリケーションでアクセスおよび更新トークンを無期限に使用する必要がある場合 (これはオフライン アクセスでは一般的なシナリオです)、更新トークンを安全に保存することが重要です。

警告

セキュリティ トークンにより、組織の Microsoft Entra ID で保護されているリソースに悪意のあるアクターがアクセスできるようになる恐れがあるため、これらのトークンの保存に伴うリスクと責任を慎重に検討してください。 組織のディレクトリ (Microsoft Entra ディレクトリ - マルチテナント) のアカウントを対象とするアプリケーションのセキュリティ違反は、特に甚大な被害を及ぼす可能性があります。

アクセス トークン自体がリソースにアクセスできるため、アクセス トークンを保存すると、セキュリティ リスクが大きくなります。 アクセス トークンを保存するのではなく、必要に応じてアクセス トークンを取得することをお勧めします。 更新トークンのみを安全に、アクセス トークンの場合と同じくらい厳密に保存してください。

必要に応じて、更新トークンがセキュリティ侵害された場合に、それを取り消すことができます。

考えられるユース ケース

このソリューションでは、Azure Key Vault、Azure Functions、Azure DevOps を使用して、OBO 更新トークンを安全に更新および保存します。

アーキテクチャ

キーとトークンの更新プロセスを示す図。

このアーキテクチャの Visio ファイルをダウンロードします。

データフロー

  • Azure Key Vault により、各 Microsoft Entra ID テナントのシークレット暗号化キーが保持されます。
  • Azure Functions のタイマーでトリガーされる関数により、Key Vault から最新の秘密鍵が取得されます。 Azure Functions の別の関数により、Microsoft ID プラットフォームから更新トークンが取得され、最新の秘密鍵バージョンを使用して保存されます。
  • データベースには、最新の暗号化キーと不透明データが格納されます。
  • Azure DevOps の継続的デリバリー パイプラインによって、シークレットのローテーションとトークンの更新プロセスの管理と同期が行われます。

コードとしてのインフラストラクチャ (IaC) または継続的インテグレーションとデリバリー (CI/CD) のために既に Azure Pipelines を使用している場合、Pipelines はキーのローテーションの戦略を追加するのに便利な場所です。 シークレットを設定および取得するためのパスを制限しているのであれば、Azure Pipelines を使用する必要はありません。

次のポリシーを適用して、Azure DevOps サービス接続のサービス プリンシパルによって Key Vault にシークレットを設定できるようにします。 <Key Vault Name> および <Service Connection Principal> 変数を、環境に合った正しい値に置き換えます。

az keyvault set-policy --name $<Key Vault Name> --spn $<Service Connection Principal> --secret-permissions set

キーを作成および更新するよう Azure Pipelines を設定したら、パイプラインを定期的に実行するようにスケジュール設定できます。 パイプラインにより、Key Vault シークレットがキーのローテーションと同期するように更新され、暗号化されたトークンは新しいシークレット バージョンで保存されます。 詳細については、「パイプラインのスケジュールを構成する」を参照してください。

マネージド ID

Azure Functions などの Azure サービスが Key Vault にアクセスするには、サービスのマネージド ID を使用する方法がお勧めです。 アクセス権の付与は、Azure portal、Azure CLI を通して (IaC のシナリオの場合は Azure Resource Manager (ARM) テンプレートを通して) 行えます。

Azure portal

Azure portal で Key Vault アクセス ポリシーを追加して、Azure Functions のマネージド ID オブジェクト ID に対して、シークレットの取得設定を許可します。 詳細については、「システム割り当て ID を追加する」と「App Service と Azure Functions の Key Vault 参照を使用する」を参照してください。

Azure portal でマネージド ID を有効にする方法を示すスクリーンショット。

Azure CLI

Azure CLI を使用して Azure Key Vault ポリシーを設定することもできます。

az keyvault set-policy --name $<Key Vault Name> --spn $<Service Connection Principal> --secret-permissions set
az keyvault set-policy --name $<Key Vault Name> --spn $<Managed Identity Principal> --secret-permissions get

ARM テンプレート

次の ARM テンプレートでは、Azure Key Vault へのアクセス権が Azure Functions に与えられます。 *** 変数を、環境に合った正しい値に置き換えます。

{
  "type": "Microsoft.KeyVault/vaults",
  "apiVersion": "2019-09-01",
  "name": "***",
  "location": "***",
  "properties": {
    "sku": {
      "family": "A",
      "name": "standard"
    },
    "tenantId": "***",
    "enableSoftDelete": true,
    "enabledForDeployment": false,
    "enabledForTemplateDeployment": false,
    "enabledForDiskEncryption": false,
    "accessPolicies": [
      {
        "tenantId": "***",
        "objectId": "<Managed Identity Principal>",
        "permissions": {
          "secrets": [
            "get"
          ]
        }
      },
      {
        "tenantId": "***",
        "objectId": "<Service Connection Principal>",
        "permissions": {
          "secrets": [
            "set"
          ]
        }
      }
    ]
  }
}

トークンの格納

任意のデータベースを使用して、暗号化された形式でトークンを格納できます。 次の図は、更新トークンをデータベースに格納するシーケンスを示しています。

トークンの追加のシーケンスを示す図。

このシーケンスには、userId()secretId() の 2 つの関数があります。 これらの関数は、token.oidtoken.tidtoken.sub の組み合わせとして定義できます。 詳細については、「id_token を使用する」を参照してださい。

暗号化キーがシークレットとして格納されているので、Azure Key Vault で最新バージョンのキーを参照できます。

トークンの使用法

キーの使用法は単純です。 次のシーケンスでは、最新のキー バージョンに基づいてキーのクエリを実行します。

格納されているトークンの使用のシーケンスを示す図。

トークンの更新は DoWork 関数と無関係なので、Azure Functions では Durable Functions を使用して DoWork およびトークンの更新を非同期的に実行できます。 Durable Functions を使用した HTTP によってトリガーされる関数の詳細については、「HTTP 機能」を参照してください。

HTTP 要求パイプラインで Azure Key Vault を使用することはお勧めできません。そのため、適切なタイミングで応答をキャッシュしてください。 この例では、getSecret(secretId, secretVersion) の呼び出しに対する Key Vault の応答はキャッシュ可能です。

キーのローテーションとトークンの更新

更新トークンを更新するのと同時に秘密鍵をローテーションすることができるため、最新のトークンが最新バージョンの暗号化シークレットで暗号化されます。 このプロセスでは、タイマー トリガーに組み込み Azure Functions サポートを使用します。 詳しくは、「Azure Functions のタイマー トリガー」を参照してください。

次のシーケンス図は、キーのローテーションとトークンの更新を同期するプロセスを示しています。

キーのローテーションとトークンの更新を同期するシーケンスを示す図。

ユーザーとアクセス制御

Microsoft ID プラットフォームでは、セキュリティ侵害された場合に更新トークンを取り消す機能が提供されています。 「トークンの失効」と「Revoke-AzureADUserAllRefreshToken」を参照してください。

Note

Azure AD および MSOnline PowerShell モジュールは、2024 年 3 月 30 日の時点で非推奨となります。 詳細については、非推奨の最新情報を参照してください。 この日以降、これらのモジュールのサポートは、Microsoft Graph PowerShell SDK への移行支援とセキュリティ修正プログラムに限定されます。 非推奨になるモジュールは、2025 年 3 月 30 日まで引き続き機能します。

Microsoft Entra ID (旧称 Azure AD) を使用するには、Microsoft Graph PowerShell に移行することをお勧めします。 移行に関する一般的な質問については、「移行に関する FAQ」を参照してください。 注: MSOnline のバージョン 1.0.x では、2024 年 6 月 30 日以降に中断が発生する可能性があります。

Microsoft Entra ID からユーザーを削除するには、単にユーザーのレコードを削除します。 ユーザーごとにアプリケーションのアクセス権を削除するには、ユーザー データの refreshToken 部分を削除します。

ターゲット テナント内のすべてのユーザーなど、ユーザーのグループのアクセス権を削除するには、Azure Pipelines を使用して、secretId() に基づいてグループのシークレットを削除します。

共同作成者

この記事は、Microsoft によって保守されています。 当初の寄稿者は以下のとおりです。

プリンシパル作成者:

次のステップ