Konfigurowanie agenta do używania protokołu OAuth

Agent używa OAuth do logowania użytkowników i otrzymywania tokenów dla zasobów w dalszej części (takich jak Microsoft Graph), bez konieczności samodzielnego obsługiwania poświadczeń uwierzytelniających. Usługa Azure Bot Service zarządza wymianą tokenów, a agent pobiera powstały token użytkownika podczas tury.

Omówienie

Wykorzystanie OAuth w agencie obejmuje trzy czynności:

  1. Konfiguruj OAuth na Azure Bot i rejestrację aplikacji: stwórz jedno lub więcej połączeń OAuth na swoim zasobie Azure Bot, każde wspierane przez rejestrację aplikacji Microsoft Entra ID. Najczęściej stosowane podejście do dodawania autoryzacji użytkownika za pomocą federacyjnego poświadczenia tożsamości to najczęstsze rozwiązanie. Obsługiwane są także inne typy poświadczeń, takie jak wpisy tajne klienta lub certyfikaty. Pełny zestaw opcji można znaleźć w artykule Podstawy uwierzytelniania usługi Bot Service.
  2. Konfiguruj odpowiednie ustawienia w agencie: każde połączenie OAuth na Azure Bot mapuje się na jedną procedurę OAuth w konfiguracji agenta. Zobacz Ustawienia. Ogólne ustawienie agenta znajdziesz w artykule Co to jest Zestaw SDK agentów usługi Microsoft 365.
  3. Używaj tokenów w kodzie: podczas tury pobierz token użytkownika — lub wykonaj wymianę On-Behalf-Of (OBO) — za pomocą interfejsu API autoryzacji użytkownika agenta. Zobacz temat Użyj tokenu w kodzie (nie-OBO) oraz Użyj tokena w kodzie (OBO).

Miej na uwadze następujące koncepcje, czytając resztę tego artykułu:

  • Azure Bot może zawierać wiele połączeń OAuth. Na przykład jedno połączenie dla Microsoft Graph, a drugie dla GitHub. Każde połączenie jest konfigurowane niezależnie na Azure Bot.
  • Istnieje relacja 1:1 między połączeniem OAuth na Azure Bot a procedurą obsługi OAuth w agencie. Ustawienie procedury obsługi AzureBotOAuthConnectionName nazywa połączenie Azure Bot, którego używa. Aby użyć dwóch połączeń, zdefiniuj dwie procedury obsługi.
  • Interfejs API autoryzacji użytkownika agenta to powierzchnia, którą wywołujesz w kodzie. W .NET jest to AgentApplication.UserAuthorization — na przykład GetTurnTokenAsync to odczyt tokenu, a ExchangeTurnTokenAsync to wykonanie wymiany OBO. Równoważne powierzchnie to authorization w JavaScript i auth w Python.

Aby uzyskać próbki robocze, zobacz próbki automatycznego logowania i OBO:

Wsparcie językowe dla OAuth

Zestaw SDK agentów obsługuje OAuth dla .NET, JavaScript i Python. Podstawowe koncepcje są takie same we wszystkich językach: procedury obsługi OAuth, dołączanie procedur obsługi do tras oraz wymiana OBO. Różnią się jedynie format konfiguracji i nazwy interfejsu API procedury obsługi:

Język Gdzie konfigurujesz Powierzchnia interfejsu API
.NET appsettings.json (lub kodem w Program.cs) AgentApplication.UserAuthorization
JavaScript Zmienne środowiskowe .env AgentApplication.authorization
Python Zmienne środowiskowe .env AgentApplication.auth

W JavaScript i Python klucze .env używają tych samych nazw hierarchicznych co struktura appsettings.json .NET, przy czym każdy poziom jest oddzielony podwójnym podkreśleniem (__). Klucze JavaScript zachowują nazwy liści zapisane w konwencji camel case, przedstawione w tabelach (na przykład, azureBotOAuthConnectionName). Klucze Python są oznaczone wielką literą (na przykład AZUREBOTOAUTHCONNECTIONNAME).

Ważne

Globalne automatyczne logowanie (AutoSignIn) i DefaultHandlerName są obsługiwane tylko w .NET. W JavaScript i Python przypisujesz obsługę OAuth do konkretnych tras, jak pokazano w Konfiguracji na trasę.

Ustawienia

Obiekt autoryzacji użytkownika w ramach AgentApplication określa sposób, w jaki agent pozyskuje tokeny użytkowników. Co najmniej każda procedura obsługi nazywa połączenie Azure Bot OAuth, którego używa. Poniższe przykłady pokazują minimalną strukturę w każdym języku. Poniższe tabele opisują pozostałe dostępne właściwości, a sekcje OBO obejmują ustawienia OBOConnectionName i ustawienia OBOScopes.

W .NET konfiguruj autoryzację użytkownika pod AgentApplication w appsettings.json:

  "AgentApplication": {
    "UserAuthorization": {
      "DefaultHandlerName": "{{handler-name}}",
      "AutoSignIn": true | false,
      "Handlers": {
        "{{handler-name}}": {
          "Settings": {
            "AzureBotOAuthConnectionName": "{{azure-bot-connection-name}}"
          }
        }
      }
    }
  }

W JavaScript konfiguruj autoryzację użytkownika za pomocą zmiennych środowiskowych w pliku .env:

# Connection used to authenticate the agent itself
connections__serviceConnection__settings__clientId=
connections__serviceConnection__settings__clientSecret=
connections__serviceConnection__settings__tenantId=
connectionsMap__0__connection=serviceConnection
connectionsMap__0__serviceUrl=*

# OAuth handler named "{{handler-name}}"
AgentApplication__UserAuthorization__Handlers__{{handler-name}}__Settings__azureBotOAuthConnectionName={{azure-bot-connection-name}}

W Python konfiguruj autoryzację użytkownika za pomocą zmiennych środowiskowych w pliku .env:

# Connection used to authenticate the agent itself
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID=
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET=
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID=

# OAuth handler named "{{handler-name}}"
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__{{handler-name}}__SETTINGS__AZUREBOTOAUTHCONNECTIONNAME={{azure-bot-connection-name}}

Właściwości UserAuthorization

Poniższa tabela przedstawia główne właściwości UserAuthorization, które określają, jak wybierane są handlery oraz jak pozyskiwane są tokeny dla każdej przychodzącej aktywności.

Właściwość Wymagania Type Podpis
DefaultHandlerName Nie (zalecane) string Tylko .NET. Nazwa programu obsługi używanego, gdy warunek AutoSignIn jest prawdziwy i nie określono zastąpienia dla poszczególnych tras.
AutoSignIn Nie bool lub użytkownik delegowany Tylko .NET. Jeśli wartość to prawda (domyślnie), agent próbuje uzyskać token dla każdej aktywności przychodzącej. Zastąp w czasie wykonywania za pomocą Options.AutoSignIn, aby filtrować typy działań.
Handlers Tak (co najmniej jedno) obiekt (słownik) Mapowanie nazwy procedury obsługi na jej konfigurację. Każdy klucz musi być unikatowy.

W .NET, aby ograniczyć zakres aktywności objętych automatycznym logowaniem, ustaw predykat podobny do: Options.AutoSignIn = (context, ct) => Task.FromResult(context.Activity.IsType(ActivityTypes.Message));. JavaScript i Python nie obsługują globalnego automatycznego logowania. Zamiast tego logowanie się w zakresie zakresu przypisuje konkretne nazwy procedur obsługi do poszczególnych tras, jak pokazano w przykładach na każdą trasę.

Właściwości konfiguracji

W poniższej tabeli opisano zagnieżdżony obiekt Settings zastosowany do pojedynczej procedury obsługi OAuth, odpowiadającej za prezentację karty logowania, zachowanie ponawiania prób, limity czasu i opcjonalną konfigurację wymiany typu OBO.

Właściwość Wymagania Type Podpis
AzureBotOAuthConnectionName Tak string Nazwa połączenia OAuth zdefiniowana na zasobie Azure bot.
OBOConnectionName Nie (tylko OBO) string Nazwa połączenia zestawu SDK agentów używanego do przeprowadzania wymiany tokenów „w imieniu”.
OBOScopes Nie (tylko OBO) ciąg[] Zakresy żądane podczas wymiany w modelu OBO. Jeśli pominięto z OBOConnectionName, możesz ręcznie wywołać ExchangeTurnTokenAsync .
Title Nie string Niestandardowy tytuł karty logowania. Wartość domyślna to Zaloguj się.
Text Nie string Tekst przycisku karty logowania. Wartość domyślna to „Zaloguj się”.
InvalidSignInRetryMax Nie liczba całkowita Maksymalna liczba prób dozwolona, gdy użytkownik wprowadzi nieprawidłowy kod. Wartość domyślna to 2.
InvalidSignInRetryMessage Nie string Komunikat wyświetlany po nieprawidłowym wpisaniu kodu. Domyślnie Nieprawidłowy kod logowania. Proszę wpisać 6-cyfrowy kod.
Timeout Nie int (ms) Liczba milisekund przed wygaśnięciem trwającej próby logowania. Domyślna wartość to 900000 (15 minut).

Notatka

AzureBotOAuthConnectionName, OBOConnectionName, OBOScopes, Title oraz Text dotyczą wszystkich trzech języków (z zachowaniem wielkości liter kluczy dla poszczególnych języków, zgodnie z opisem w Obsługa języków w OAuth). InvalidSignInRetryMax, InvalidSignInRetryMessage oraz Timeout są ustawieniami .NET.

Jaki typ należy wybrać?

Skorzystaj z poniższej tabeli, aby zdecydować, które podejście najlepiej pasuje do danego scenariusza.

Opcja wyboru Użyj, kiedy
Automatyczne logowanie (tylko .NET) Chcesz, aby każde przychodzące działanie automatycznie uzyskiwało token, lub aby filtrowany podzbiór (na przykład tylko komunikaty albo wszystko oprócz zdarzeń) robił to przez przekazanie predykatu do UserAuthorizationOptions.AutoSignIn. Obsługiwane tylko w .NET.
Na trasę Tylko określone procedury obsługi tras potrzebują tokenów lub różne trasy muszą korzystać z różnych połączeń OAuth (a co za tym idzie, różnych tokenów). Ta opcja jest jedyną dostępną w JavaScript i Python. W .NET jest to dodatek do globalnego automatycznego logowania. Jeśli obie opcje są włączone w .NET, przetwarzanie ma dostęp do tokenów z każdej.

Używanie tokenu w kodzie (inne niż OBO)

W tej sekcji pokazano, jak pobrać i użyć tokenu użytkownika bezpośrednio zwróconego przez połączenie OAuth usługi Azure Bot bez przeprowadzania wymiany w imieniu użytkownika. W .NET możesz używać globalnych automatycznych logowań lub obsługi trasy. JavaScript i Python używają tylko obsługi na trasę. W obsłudze aktywności pobierz token (GetTurnTokenAsync w .NET, authorization.getToken JavaScript, auth.get_token w Python) tak późno, jak to możliwe, aby zestaw SDK mógł odświeżyć token, jeśli jest bliski wygaśnięcia. Poniższe przykłady ilustrują oba podejścia.

Automatyczne logowanie (tylko .NET)

Notatka

Globalne automatyczne logowanie i DefaultHandlerName są dostępne tylko w .NET. Dla JavaScript i Python używaj konfiguracji na trasę.

Użyj tej konfiguracji, gdy globalne automatyczne logowanie powinno uzyskać token dla każdej przychodzącej aktywności bez konieczności określania procedur obsługi dla poszczególnych tras.

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

Kod agenta będzie wyglądać mniej więcej tak:

public class MyAgent : AgentApplication
{
    [MessageRoute]
    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext);

        // use the token 
    }
}

Konfiguracja na trasę

Używaj konfiguracji na poziomie poszczególnych tras, gdy potrzebujesz precyzyjnej kontroli: tylko trasy, które wyraźnie oznaczysz, uzyskują tokeny. Konfiguracja na każdą trasę ma następujące zalety:

  • Ogranicza niepotrzebne odzyskiwanie tokenów.
  • Pozwala na różne trasy celowania w różne połączenia OAuth (a tym samym różne zasoby lub zakresy).
  • Pozwala łączyć ścieżki uwierzytelnione i nieuwierzytelnione w ramach tego samego agenta.

W poniższym przykładzie pojedyncza procedura obsługi graph jest przypisana tylko do trasy komunikatu.

W .NET globalne automatyczne logowanie jest wyłączone, a procedura obsługi graph jest dołączana do trasy za pomocą autoSignInHandlers.

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

Kod agenta będzie wyglądać mniej więcej tak:

public class MyAgent : AgentApplication
{
    [MessageRoute(autoSignInHandlers: "graph")]
    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext, "graph");

        // use the token
    }
}

W JavaScript przekaż tablicę nazw procedur obsługi jako ostatni argument do rejestracji trasy. Tylko ta trasa wyzwala logowanie dla procedury obsługi graph.

AgentApplication__UserAuthorization__Handlers__graph__Settings__azureBotOAuthConnectionName=teams_sso
AgentApplication__UserAuthorization__Handlers__graph__Settings__title=Graph Sign In
AgentApplication__UserAuthorization__Handlers__graph__Settings__text=Sign in with Microsoft Graph

Kod agenta będzie wyglądać mniej więcej tak:

class MyAgent extends AgentApplication {
  constructor () {
    super({ storage: new MemoryStorage() })
    // the `graph` handler runs only for this route
    this.onMessage('-me', this._profileRequest, ['graph'])
  }

  private _profileRequest = async (context, state) => {
    const tokenResponse = await this.authorization.getToken(context, 'graph')

    // use tokenResponse.token
  }
}

W Python przekaż auth_handlers do dekoratora tras. Tylko ta trasa wyzwala logowanie dla procedury obsługi GRAPH.

AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__GRAPH__SETTINGS__AZUREBOTOAUTHCONNECTIONNAME=teams_sso

Kod agenta będzie wyglądać mniej więcej tak:

@AGENT_APP.message(re.compile(r"^/(me|profile)$", re.IGNORECASE), auth_handlers=["GRAPH"])
async def profile_request(context: TurnContext, state: TurnState) -> None:
    token_response = await AGENT_APP.auth.get_token(context, "GRAPH")

    # use token_response.token

Odzyskaj token podczas tury

Odzyskaj token użytkownika, kiedy tylko go potrzebujesz podczas tury. Można wywołać go wielokrotnie. Wywołaj ją bezpośrednio przed użyciem, aby logika odświeżania była, w razie potrzeby, transparentnie obsługiwana.

Język Zadzwoń
.NET GetTurnTokenAsync(turnContext, handlerName)
JavaScript authorization.getToken(context, handlerName)
Python auth.get_token(context, handler_name)

Używanie tokenu w kodzie (OBO)

On-Behalf-Of (OBO) opiera się na początkowym logowaniu użytkownika, które zwraca token wymienny. Wymaga to, aby zakresy połączenia OAuth zawierały taki, który odpowiada zakresowi udostępnianemu przez downstream API (na przykład, jeśli udostępniany zakres to defaultScopes, skonfigurowany zakres może być api://botid-{{clientId}}/defaultScopes). Następnie zestaw SDK agentów wykonuje wymianę w bibliotece Microsoft Authentication Library (MSAL) przy użyciu skonfigurowanego połączenia zidentyfikowanego przez OBOConnectionName oraz listy OBOScopes. Gdy zarówno OBOConnectionName, jak i OBOScopes są obecne w konfiguracji, wymiana odbywa się automatycznie, a docelowy token można uzyskać za pomocą wywołania standardowego tokenu (GetTurnTokenAsync / getToken / get_token). Jeśli brakuje któregoś z nich, możesz jawnie przeprowadzić tę wymianę w czasie wykonywania (ExchangeTurnTokenAsync w .NET, authorization.exchangeToken i JavaScript, auth.exchange_token w Python), co pozwala dynamicznie określić listę połączeń lub zakresów.

OBO w konfiguracji

Stosuj ten wzorzec, gdy znasz docelowy zasób i zakresy wymagane podczas konfiguracji. Po podaniu elementów OBOConnectionName i OBOScopes pakiet SDK automatycznie wykonuje wymianę w imieniu użytkownika podczas logowania. Oznacza to, że kolejne wywołania standardowego tokenu zwracają token OBO bez konieczności pisania dodatkowego kodu podczas działania aplikacji.

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

Kod agenta będzie wyglądać mniej więcej tak:

public class MyAgent : AgentApplication
{
    [MessageRoute(autoSignInHandlers: "graph")]
    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        // returns the OBO token because OBOConnectionName and OBOScopes are configured
        var token = await UserAuthorization.GetTurnTokenAsync(turnContext, "graph");

        // use the token
    }
}

W JavaScript zdefiniuj połączenie OBO w mapie połączeń i odwołaj je z obsługi za pomocą oboConnectionName i oboScopes.

# Agent's own connection
connections__serviceConnection__settings__clientId=
connections__serviceConnection__settings__clientSecret=
connections__serviceConnection__settings__tenantId=

# OBO connection
connections__oboConnection__settings__clientId=
connections__oboConnection__settings__clientSecret=
connections__oboConnection__settings__tenantId=

connectionsMap__0__connection=serviceConnection
connectionsMap__0__serviceUrl=*
connectionsMap__1__connection=oboConnection
connectionsMap__1__serviceUrl=obo

AgentApplication__UserAuthorization__Handlers__graph__Settings__azureBotOAuthConnectionName=teams_sso
AgentApplication__UserAuthorization__Handlers__graph__Settings__oboConnectionName=oboConnection
AgentApplication__UserAuthorization__Handlers__graph__Settings__oboScopes=https://graph.microsoft.com/.default

Kod agenta będzie wyglądać mniej więcej tak:

class MyAgent extends AgentApplication {
  constructor () {
    super({ storage: new MemoryStorage() })
    this.onActivity('message', this._onMessage, ['graph'])
  }

  private _onMessage = async (context, state) => {
    // returns the OBO token because oboConnectionName and oboScopes are configured
    const tokenResponse = await this.authorization.getToken(context, 'graph')

    // use tokenResponse.token
  }
}

W Python zdefiniuj połączenie OBO pod CONNECTIONS i odwołaj się do niego z poziomu procedury obsługi za pomocą OBOCONNECTIONNAME i OBOSCOPES.

# Agent's own connection
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID=
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET=
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID=

# OBO connection
CONNECTIONS__OBO__SETTINGS__CLIENTID=
CONNECTIONS__OBO__SETTINGS__CLIENTSECRET=
CONNECTIONS__OBO__SETTINGS__TENANTID=

AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__GRAPH__SETTINGS__AZUREBOTOAUTHCONNECTIONNAME=teams_sso
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__GRAPH__SETTINGS__OBOCONNECTIONNAME=OBO
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__GRAPH__SETTINGS__OBOSCOPES=https://graph.microsoft.com/.default

Kod agenta będzie wyglądać mniej więcej tak:

@AGENT_APP.message(re.compile(r".*"), auth_handlers=["GRAPH"])
async def on_message(context: TurnContext, state: TurnState) -> None:
    # returns the OBO token because OBOCONNECTIONNAME and OBOSCOPES are configured
    token_response = await AGENT_APP.auth.get_token(context, "GRAPH")

    # use token_response.token

Wymiana OBO w środowisku uruchomieniowym

Używaj wymiany w czasie działania, gdy nie możesz naprawić zasobu do klienta, zakresów czy połączenia w konfiguracji. Sytuacja ta zdarza się na przykład, gdy zakresy zależą od dzierżawcy, roli użytkownika lub flagi funkcji. W tym modelu opcjonalnie konfigurujesz połączenie OBO, a następnie wywołujesz metodę wymiany z wybranymi przez siebie celownikami podczas tury. Otrzymujesz wymieniony token, który możesz natychmiast zastosować.

Wywołaj ExchangeTurnTokenAsync z zakresami wybranymi w momencie tury.

  "AgentApplication": {
    "UserAuthorization": {
      "AutoSignIn": false,
      "Handlers": {
        "graph": {
          "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"
        ]
      }
    }
  },

Kod agenta będzie wyglądać mniej więcej tak:

public class MyAgent : AgentApplication
{
    [MessageRoute(autoSignInHandlers: "graph")]
    public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
    {
        var scopes = GetScopes();

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

        // use the token
    }
}

Wywołaj authorization.exchangeToken z nazwą procedury obsługi i z zakresami wybranymi w momencie tury.

connections__oboConnection__settings__clientId=
connections__oboConnection__settings__clientSecret=
connections__oboConnection__settings__tenantId=

connectionsMap__1__connection=oboConnection
connectionsMap__1__serviceUrl=obo

AgentApplication__UserAuthorization__Handlers__graph__Settings__azureBotOAuthConnectionName=teams_sso
AgentApplication__UserAuthorization__Handlers__graph__Settings__oboConnectionName=oboConnection

Kod agenta będzie wyglądać mniej więcej tak:

class MyAgent extends AgentApplication {
  constructor () {
    super({ storage: new MemoryStorage() })
    this.onActivity('message', this._onMessage, ['graph'])
  }

  private _onMessage = async (context, state) => {
    const scopes = getScopes()
    const exchangedToken = await this.authorization.exchangeToken(context, 'graph', { scopes })

    // use exchangedToken.token
  }
}

Wywołaj auth.exchange_token, podając zakresy wybrane w momencie wykonania tury oraz nazwę procedury obsługi.

CONNECTIONS__MCS__SETTINGS__CLIENTID=
CONNECTIONS__MCS__SETTINGS__CLIENTSECRET=
CONNECTIONS__MCS__SETTINGS__TENANTID=

AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__MCS__SETTINGS__AZUREBOTOAUTHCONNECTIONNAME=teams_sso
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__MCS__SETTINGS__OBOCONNECTIONNAME=MCS

Kod agenta będzie wyglądać mniej więcej tak:

@AGENT_APP.message(re.compile(r".*"), auth_handlers=["MCS"])
async def on_message(context: TurnContext, state: TurnState) -> None:
    scopes = get_scopes()
    token_response = await AGENT_APP.auth.exchange_token(context, scopes, "MCS")

    # use token_response.token

Regionalne ustawienia OAuth

W regionach spoza USA zaktualizuj punkt końcowy usługi tokenów używany przez agenta.

Poniższy przykład przedstawia konfigurację .NET. Dodaj to do appsettings.json:

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

Dla service-endpoint-url należy użyć odpowiedniej wartości z poniższej tabeli dla botów chmury publicznej z lokalizacją danych w wybranym regionie.

URI Region
https://europe.api.botframework.com Europa
https://unitedstates.api.botframework.com Stany Zjednoczone
https://india.api.botframework.com Indie