次の方法で共有


OAuth を使用するように .NET エージェントを構成する

.NET エージェントの OAuth は、最初に Azure Bot リソースと対応するアプリの登録にプロビジョニングされます。 エージェント ランタイムは、 AgentApplication 自動サインイン機能を使用してユーザー トークンを取得して更新します。 自動サインインは、グローバル (すべてのアクティビティの種類) または選択的に実行できるため、特定のルートまたはアクティビティの種類のみがトークンを要求できます。

複数の OAuth ハンドラーを構成に登録して特定のルートに割り当てたり、どこでも使用される 1 つの既定のハンドラーを宣言したりできます。 各ハンドラーは、Azure 側が構成されている場合、オプションで代理 (OBO) のやり取りを実行できます。 クイック スタートについては、 AutoSignIn サンプルを参照するか、ここに示す構成を既存のエージェントに変更します。

以降のセクションでは、ターン中に UserAuthorizationを構成し、グローバルアプローチとルートごとのアプローチを決定し、トークン (標準と OBO) を取得する方法について説明します。 米国以外のデプロイに関するリージョン ガイダンスも提供されています。

.NET エージェントは、appsettings または Program.cs のコードを使用して構成されます。 このドキュメントでは、appsettings の使用について詳しく説明します。

設定

UserAuthorization内のAgentApplication オブジェクトは、ユーザー トークンの取得方法を制御します。 次の JSON は、階層構造の後に、 UserAuthorization と入れ子になった Settings オブジェクトの各プロパティを記述するテーブルを示しています。

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "{{handler-name}}",
      "AutoSignIn": true | false,
      "Handlers": {
        "{{handler-name}}": {
          "Settings": {
            "AzureBotOAuthConnectionName": "{{azure-bot-connection-name}}",
            "OBOConnectionName": "{{connection-name}}",
            "OBOScopes": [
              "{{obo-scope}}"
            ],
            "Title": "{{signin-card-title}}",
            "Text": "{{signin-card-button-text}}",
            "InvalidSignInRetryMax": {{int}},
            "InvalidSignInRetryMessage": {{invalid-attempt-message}},
            "Timeout": {{timeout-ms}}
          }
        }
      }
    }
  }

UserAuthorization プロパティ

次の表に、ハンドラーの選択方法と、受信アクティビティごとにトークンを取得する方法を決定する最上位の UserAuthorization プロパティを示します。

プロパティ 必須 タイプ Description
DefaultHandlerName いいえ (推奨) 文字列 AutoSignInが true と評価され、ルートごとのオーバーライドが指定されていない場合に使用されるハンドラーの名前。
AutoSignIn いいえ bool またはデリゲート true (既定値) の場合、エージェントは受信アクティビティごとにトークンの取得を試みます。は、アクティビティの種類をフィルター処理する Options.AutoSignIn を使用して実行時にオーバーライドできます。
Handlers はい (少なくとも 1 つ) オブジェクト (ディクショナリ) ハンドラー名とその構成のマッピング。 各キーは一意である必要があります。

自動サインインが適用されるアクティビティを制限するには、次のような述語を設定します: Options.AutoSignIn = (context, ct) => Task.FromResult(context.Activity.IsType(ActivityTypes.Message));

設定プロパティ

次の表では、個々の OAuth ハンドラーに適用される入れ子になった Settings オブジェクトについて説明し、サインイン カードの表示、再試行動作、タイムアウト、およびオプションの OBO 交換構成を制御します。

プロパティ 必須 タイプ Description
AzureBotOAuthConnectionName イエス 文字列 Azure Bot リソースで定義されている OAuth 接続名。
OBOConnectionName いいえ (OBO のみ) 文字列 On‑Behalf‑Of トークン交換の実行に使用される Agents SDK 接続の名称。
OBOScopes いいえ (OBO のみ) string[] OBO 交換中に要求されたスコープ。 OBOConnectionName で省略した場合は、 ExchangeTurnTokenAsync を手動で呼び出すことができます。
Title いいえ 文字列 カスタムサインインカードのタイトルは、既定で[サインイン]に設定されます。
Text いいえ 文字列 サインイン カード ボタンのテキスト。既定値は [サインインしてください] です
InvalidSignInRetryMax いいえ 整数 (int) ユーザーが無効なコードを入力したときに許容される再試行の最大数。既定値は 2 です。
InvalidSignInRetryMessage いいえ 文字列 無効なコード エントリの後に表示されるメッセージ。の既定値は 無効なサインイン コードです。6 桁のコードを入力してください。
Timeout いいえ int (ms) 進行中のサインイン試行が期限切れになるまでのミリ秒数。 既定値は 900000 (15 分) です。

どのような種類を使用しますか?

次の表を使用して、シナリオに適したアプローチを決定します。

選択肢 次の場合に使用します。
自動サインイン すべての受信アクティビティでトークンを自動的に取得する場合や、 UserAuthorizationOptions.AutoSignInする述語を指定してフィルター処理されたサブセット (メッセージのみ、イベントを除くすべてなど) が必要です。
ルートごと 特定のルート ハンドラーのみがトークンを必要とするか、異なるルートで異なる OAuth 接続 (したがって異なるトークン) を使用する必要があります。 これは、グローバル自動サインインの追加機能です。 両方が有効になっている場合、ターンはそれぞれのトークンにアクセスできます。

コードでトークンを使用する (OBO 以外)

このセクションでは、On-Behalf-Of 交換を実行せずに、Azure Bot OAuth 接続によって直接返されるユーザー トークンを取得して使用する方法について説明します。 最初に、グローバル自動サインインハンドラーとルートごとのハンドラーのどちらを使用するかを決定します。その後、アクティビティ ハンドラー内でできるだけ遅く UserAuthorization.GetTurnTokenAsync 呼び出して、期限が近づいている場合に SDK がトークンを更新できるようにします。 次の例は、両方のパターンを示しています。

自動サインインのみの構成

この構成は、グローバル自動サインインが、ルートごとのハンドラーを指定することなく、すべての受信アクティビティのトークンを取得する必要がある場合に使用します。

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "auto",
      "Handlers": {
        "auto": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
          }
        }
      }
    }
  },

エージェント コードは次のようになります。

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext);

        // use the token 
    }
}

ルート単位のみの構成

きめ細かい制御が必要な場合は、ルートごとの構成を使用します。トークンの取得を明示的にマークしたルートのみ。 ルートごとの構成では、不要なトークンの取得が減り、異なるルートが個別の OAuth 接続 (および異なるリソースまたはスコープ) を対象とすることができ、同じエージェント内で認証されたルートと認証されていないルートを混在させることが可能になります。 次の例では、グローバル自動サインインが無効になり、1 つの messageOauth ハンドラーがメッセージ ルートにのみアタッチされます。

  "AgentApplication": {
    "UserAuthorization": {
      "AutoSignIn": false,
      "Handlers": {
        "messageOauth": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
          }
        }
      }
    }
  },

エージェント コードは次のようになります。

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last, autoSignInHandlers: ["messageOauth"]);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext, "messageOauth");

        // use the token
    }
}

GetTurnTokenAsync を使用する

ターン中にユーザー トークンが必要な場合は常に GetTurnTokenAsync を呼び出します。 複数回呼び出すことができます。 更新ロジック (必要な場合) が透過的に処理されるように、使用する直前に呼び出します。

コードでトークンを使用する (OBO)

オンビヘイーフオブ (OBO) は、交換可能なトークンを返す初回ユーザーサインインに依存します。 そのためには、OAuth 接続のスコープに、ダウンストリーム API によって公開されるスコープに対応するスコープを含める必要があります (たとえば、公開されているスコープが defaultScopes場合、構成されたスコープが api://botid-{{clientId}}/defaultScopesされる可能性があります)。 その後、Agents SDK は、 OBOConnectionName によって識別される構成済みの接続と OBOScopesの一覧を使用して、Microsoft Authentication Library (MSAL) 交換を実行します。 構成に OBOConnectionNameOBOScopes の両方が存在する場合、交換は自動的に行われ、 GetTurnTokenAsyncを使用して最終的なトークンを取得します。 いずれかが見つからない場合は、 ExchangeTurnTokenAsyncを使用して実行時に明示的に交換を実行し、接続またはスコープ リストを動的に解決できます。

構成内の OBO

このパターンは、構成時に必要なダウンストリーム リソースとスコープがわかっている場合に使用します。 OBOConnectionNameOBOScopesの両方を指定すると、SDK はサインイン時に自動的に On-Behalf-Of 交換を実行します。 つまり、後続の呼び出し GetTurnTokenAsync 、追加のランタイム コードを必要とせず、OBO トークンを直接返します。

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "auto",
      "Handlers": {
        "auto": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
            "OBOConnectionName": "ServiceConnection",
            "OBOScopes": [
              "https://myservicescope.com/.default"
            ]
          }
        }
      }
    }
  },
  "Connections": {
    "ServiceConnection": {
      "Settings": {
        "AuthType": "FederatedCredentials",
        "AuthorityEndpoint": "https://login.microsoftonline.com/{{TenantId}}",
        "ClientId": "{{ClientId}}",
        "FederatedClientId": "{{ManagedIdentityClientId}}",
        "Scopes": [
          "https://api.botframework.com/.default"
        ]
      }
    }
  },

エージェント コードは次のようになります。

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext);

        // use the token
    }
}

実行時の OBO Exchange

ダウンストリーム リソース、スコープ、または使用する必要がある接続を構成で固定できない場合 (たとえば、スコープがテナント、ユーザー ロール、機能フラグに依存する場合など) は、ランタイム交換を使用します。 このモデルでは、(必要に応じて) OBOConnectionNameを構成し、ターンタイムに決定したスコープで ExchangeTurnTokenAsync を呼び出し、すぐに適用できる交換トークンを受け取ります。

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "auto",
      "Handlers": {
        "auto": {
          "Settings": {
            "AzureBotOAuthConnectionName": "teams_sso",
            "OBOConnectionName": "ServiceConnection"
          }
        }
      }
    }
  },
  "Connections": {
    "ServiceConnection": {
      "Settings": {
        "AuthType": "FederatedCredentials",
        "AuthorityEndpoint": "https://login.microsoftonline.com/{{TenantId}}",
        "ClientId": "{{ClientId}}",
        "FederatedClientId": "{{ManagedIdentityClientId}}",
        "Scopes": [
          "https://api.botframework.com/.default"
        ]
      }
    }
  },

エージェント コードは次のようになります。

public class MyAgent : AgentApplication
{
    public MyAgent(AgentApplicationOptions options) : base(options)
    {
        OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
    }

    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var scopes = GetScopes();

        var exchangedToken = await UserAuthorization.ExchangeTurnTokenAsync(turnContext, exchangeScopes: scopes);

        // use the token
    }
}

リージョン OAuth の設定

米国以外のリージョンの場合は、エージェントによって使用されるトークン サービス エンドポイントを更新する必要があります。

次を appsettings.jsonに追加します。

"RestChannelServiceClientFactory": {
   "TokenServiceEndpoint": "{{service-endpoint-uri}}"
}

service-endpoint-urlの場合は、指定したリージョンのデータ所在地を持つパブリック クラウド ボットに対して、次の表の適切な値を使用します。

URI リージョン
https://europe.api.botframework.com ヨーロッパ
https://unitedstates.api.botframework.com 米国
https://india.api.botframework.com インド