Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
En agent använder OAuth för att logga in användare och få tokens för nedströmsresurser (såsom Microsoft Graph) utan att hantera inloggningsuppgifterna själv. Azure Bot Service hanterar tokenutbytet och agenten hämtar den resulterande användartoken under en tur.
Översikt
Att använda OAuth i en agent involverar tre aktiviteter:
- Konfigurera OAuth på Azure Bot och appregistrering: Skapa en eller flera OAuth-anslutningar på din Azure Bot-resurs, var och en backad av en Microsoft Entra ID-appregistrering. Att lägga till användarbehörighet med autentiseringsuppgifter med federerad identitet täcker det vanligaste tillvägagångssättet. Andra typer av autentiseringsuppgifter, såsom klienthemligheter eller certifikat, stöds också. För hela uppsättningen av alternativ, se grundläggande autentisering för Bot Service.
- Konfigurera matchande inställningar i agenten: Varje OAuth-anslutning på Azure Bot mappas till en OAuth-hanterare i agentens konfiguration. Mer information finns i Inställningar. För allmän agentkonfiguration, se Vad är SDK för Microsoft 365-agenter.
- Använd tokens i kod: Under en runda, hämta användartoken – eller utför ett On-Behalf-Of (OBO)-utbyte – via agentens användarauktorisations-API. Se Använd token i kod (icke-OBO) och Använd token i kod (OBO).
Ha följande begrepp i åtanke när du läser resten av den här artikeln:
- En Azure Bot kan innehålla flera OAuth-anslutningar. Till exempel en anslutning för Microsoft Graph och en annan för GitHub. Varje anslutning konfigureras oberoende på Azure Bot.
- Det finns en 1:1-relation mellan en OAuth-anslutning på Azure Bot och en OAuth-hanterare i agenten. En hanterarws
AzureBotOAuthConnectionName-inställning namnger Azure Bot-anslutningen den använder. För att använda två anslutningar, definiera två hanterare. - Agentens användarbehörighets-API är den yta du anropar i koden. I .NET är detta
AgentApplication.UserAuthorization– till exempelGetTurnTokenAsyncför att läsa en token ochExchangeTurnTokenAsyncför att utföra ett OBO-utbyte. De motsvarande ytorna ärauthorizationi JavaScript ochauthi Python.
För arbetsexempel, se automatisk inloggning och OBO-exempel för:
Språkstöd för OAuth
Agents SDK stöder OAuth för .NET, JavaScript och Python. Kärnkoncepten är desamma i alla språk: OAuth-hanterare, att koppla hanterare till rutter och OBO-utbyte. Endast konfigurationsformatet och hanterarens API-namn skiljer sig åt:
| Language | Var du konfigurerar | API-yta |
|---|---|---|
| .NET |
appsettings.json (eller kod i Program.cs) |
AgentApplication.UserAuthorization |
| JavaScript |
.env miljövariabler |
AgentApplication.authorization |
| Python |
.env miljövariabler |
AgentApplication.auth |
För JavaScript och Python använder nycklarna .env samma hierarkiska namn som .NET-strukturen appsettings.json , där varje nivå är separerad av ett dubbelt understreck (__). JavaScript-nycklar behåller lövnamnen med kamelnotation som visas i tabellerna (till exempel azureBotOAuthConnectionName). Python-nycklar är versaler (till exempel AZUREBOTOAUTHCONNECTIONNAME).
Viktigt
Global automatisk inloggning (AutoSignIn) och DefaultHandlerName stöds endast i .NET. I JavaScript och Python kopplar du OAuth-hanterare till specifika rutter, som visas i Per rutt-konfigurationen.
Inställningar
Ett användarauktoriseringsobjekt i AgentApplication styr hur agenten hämtar användartoken. Minst namnger varje hanterare den Azure Bot OAuth-anslutning den använder. Följande exempel visar den minimala strukturen i varje språk.
Tabellerna nedan beskriver resten av de tillgängliga egenskaperna, och OBO-sektionerna täcker inställningarna OBOConnectionName och OBOScopes.
I .NET, konfigurera användarauktorisering under AgentApplication i appsettings.json:
"AgentApplication": {
"UserAuthorization": {
"DefaultHandlerName": "{{handler-name}}",
"AutoSignIn": true | false,
"Handlers": {
"{{handler-name}}": {
"Settings": {
"AzureBotOAuthConnectionName": "{{azure-bot-connection-name}}"
}
}
}
}
}
I JavaScript, konfigurera användarauktorisering med miljövariabler i filen .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}}
I Python, konfigurera användarauktorisering med miljövariabler i filen .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}}
Egenskaper för UserAuthorization
Följande tabell listar toppnivåegenskaperna för UserAuthorization som avgör hur handlers väljs och hur tokens hämtas för varje inkommande aktivitet.
| Egenskap | Obligatoriskt | Type | beskrivning |
|---|---|---|---|
DefaultHandlerName |
Nej (rekommenderas) | sträng | Endast .NET. Namnet på hanteraren som används när AutoSignIn utvärderas till sant och ingen åsidosättning per väg har angetts. |
AutoSignIn |
Nej | bool eller ombud | Endast .NET. När värdet är sant (standard) försöker agenten hämta en token för varje inkommande aktivitet. Åsidosätt vid körning med Options.AutoSignIn för att filtrera aktivitetstyper. |
Handlers |
Ja (minst en) | objekt (ordlista) | Mappning av handlernamn till dess konfiguration. Varje nyckel måste vara unik. |
I .NET, för att begränsa vilka aktiviteter som automatisk inloggning gäller för, sätt ett predikat liknande: Options.AutoSignIn = (context, ct) => Task.FromResult(context.Activity.IsType(ActivityTypes.Message));. JavaScript och Python stödjer inte global automatisk inloggning. Logga istället in avgränsat genom att koppla specifika hanterarnamn till enskilda rutter, som visas i exemplen per rutt.
Egenskaper för inställningar
Följande tabell beskriver det inbäddade Settings-objektet som används för en enskild OAuth-hanterare och styr visningen av inloggningskort, återförsöksbeteende, timeouts samt valfri OBO-utbyteskonfiguration.
| Egenskap | Obligatoriskt | Type | beskrivning |
|---|---|---|---|
AzureBotOAuthConnectionName |
Ja | sträng | OAuth-anslutningsnamn definierat på Azure robot-resursen. |
OBOConnectionName |
Nej (endast OBO) | sträng | Namnet på en Agents SDK-anslutning som används för att utföra ett On-Behalf-Of-tokenutbyte. |
OBOScopes |
Nej (endast OBO) | sträng[] | Omfång som begärdes under OBO-utbytet. Om det utelämnas med OBOConnectionName, kan du manuellt anropa ExchangeTurnTokenAsync. |
Title |
Nej | sträng | Anvpassad rubrik för inloggning. Standardvärdet är Logga in. |
Text |
Nej | sträng | Knapptext för inloggningskort. Standardvärdet är Logga in. |
InvalidSignInRetryMax |
Nej | heltal | Det maximala antalet försök som tillåts när användaren anger en ogiltig kod Standard är 2. |
InvalidSignInRetryMessage |
Nej | sträng | Meddelande som visas efter att användaren har angett en ogiltig kod. Standardmeddelandet är Ogiltig inloggningskod. Ange den sexsiffriga koden. |
Timeout |
Nej | int (ms) | Antal millisekunder innan ett pågående inloggningsförsök går ut. Standardvärdet är 900 000 (15 minuter). |
Kommentar
AzureBotOAuthConnectionName, OBOConnectionName, OBOScopes, , Titleoch Text gäller för alla tre språk (med hjälp av nyckelfallet per språk som beskrivs i Språkstöd för OAuth).
InvalidSignInRetryMax, InvalidSignInRetryMessage och Timeout är .NET-inställningar.
Vilken typ ska du använda?
Använd följande tabell för att avgöra vilket angreppssätt som passar ditt scenario.
| Alternativ | Använd när |
|---|---|
| Automatisk inloggning (endast .NET) | Du vill att varje inkommande aktivitet automatiskt ska hämta en token, eller så vill du ha en filtrerad delmängd (till exempel endast meddelanden eller allt utom händelser) genom att ange ett predikat till UserAuthorizationOptions.AutoSignIn. Stöds endast i .NET. |
| Per väg | Endast specifika rutt-hanterare behöver tokens eller så måste olika rutter använda olika OAuth-anslutningar (och därmed olika tokens). Detta alternativ är det enda alternativet i JavaScript och Python. I .NET är det additivt med global automatisk inloggning. Om båda är aktiverade i .NET har turen tillgång till tokens från båda. |
Använda token i koden (icke-OBO)
Det här avsnittet visar hur du hämtar och använder användartoken som direkt returneras av din Azure robot OAuth-anslutning utan att utföra ett On-Behalf-Of-utbyte. I .NET kan du använda global automatisk inloggning eller per-rutt-hanterare. JavaScript och Python använder endast hanterare per rutt. Inuti din aktivitetshanterare, hämta token (GetTurnTokenAsync i .NET, authorization.getToken i JavaScript, auth.get_token i Python) så sent som möjligt så att SDK:n kan uppdatera token om den är nära utgång. Följande exempel illustrerar båda mönstren.
Automatisk inloggning (endast .NET)
Kommentar
Global automatisk inloggning och DefaultHandlerName är endast tillgängliga i .NET. För JavaScript och Python, använd Per-rutt-konfiguration.
Använd denna konfiguration när global automatisk inloggning ska hämta en token för varje inkommande aktivitet utan att behöva ange per-rutt-hanterare.
"AgentApplication": {
"UserAuthorization": {
"DefaultHandlerName": "auto",
"Handlers": {
"auto": {
"Settings": {
"AzureBotOAuthConnectionName": "teams_sso",
}
}
}
}
},
Din agentkod skulle se ut ungefär så här:
public class MyAgent : AgentApplication
{
[MessageRoute]
public async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
{
var token = await UserAuthorization.GetTurnTokenAsync(turnContext);
// use the token
}
}
Per-ruttkonfiguration
Använd en per-route-konfiguration när du vill ha granulär kontroll: endast de rutter som du uttryckligen markerar hämtar tokens. Per rutt-konfiguration har följande fördelar:
- Det minskar onödig token-hämtning.
- Det tillåter olika rutter att rikta in sig på distinkta OAuth-anslutningar (och därmed olika resurser eller omfattningar).
- Den låter dig blanda autentiserade och oautentiserade rutter inom samma agent.
I följande exempel är en enda graph hanterare endast kopplad till meddelanderutten.
I .NET inaktiveras global automatisk inloggning och hanteraren graph kopplas till rutten med hjälp av autoSignInHandlers.
"AgentApplication": {
"UserAuthorization": {
"AutoSignIn": false,
"Handlers": {
"graph": {
"Settings": {
"AzureBotOAuthConnectionName": "teams_sso",
}
}
}
}
},
Din agentkod skulle se ut ungefär så här:
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
}
}
I JavaScript, skicka en array av handlernamn som sista argument till ruttregistreringen. Endast den vägen utlöser inloggning för hanteraren 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
Din agentkod skulle se ut ungefär så här:
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
}
}
I Python, skicka till auth_handlers ruttdekoratören. Endast den vägen utlöser inloggning för hanteraren GRAPH .
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__GRAPH__SETTINGS__AZUREBOTOAUTHCONNECTIONNAME=teams_sso
Din agentkod skulle se ut ungefär så här:
@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
Hämta token under en tur
Hämta användartokenen när du behöver den under en tur. Du kan anropa den flera gånger. Anropa metoden direkt före användning så att uppdateringslogiken (vid behov) hanteras automatiskt.
| Language | Ring |
|---|---|
| .NET |
GetTurnTokenAsync(turnContext, handlerName) |
| JavaScript | authorization.getToken(context, handlerName) |
| Python | auth.get_token(context, handler_name) |
Använda token i koden (OBO)
On-Behalf-Of (OBO) bygger på att den initiala användarinloggningen returnerar en utbytbar token. Det kräver att OAuth-anslutningens scope inkluderar ett som motsvarar ett scope som tillgängliggörs av nedströms-API:et (till exempel om det tillgängliggjorda scopet är defaultScopes, kan det konfigurerade scopet vara api://botid-{{clientId}}/defaultScopes). Agent-SDK:n genomför därefter ett Microsofts autentiseringsbibliotek (MSAL)-tokenutbyte med en konfigurerad anslutning identifierad av OBOConnectionName och listan över OBOScopes. När både OBOConnectionName och OBOScopes finns i konfigurationen sker utbytet automatiskt, och du får den slutgiltiga tokenen via standardtokenanropet (GetTurnTokenAsync / getToken / get_token). Om någon av dem saknas kan du utföra utbytet explicit vid körning (ExchangeTurnTokenAsync i .NET, authorization.exchangeToken i JavaScript, auth.exchange_token i Python) så att du kan lösa anslutnings- eller omfångslistan dynamiskt.
OBO i konfiguration
Använd detta mönster när du vet vilken nedströmsresurs och vilka scopes du behöver vid konfigurationstillfället. När du anger både OBOConnectionName och OBOScopes utför SDK:et automatiskt OBO-utbytet (på uppdrag av) under inloggningen. Detta innebär att efterföljande anrop till standardtokenhämtaren returnerar OBO-token direkt utan att extra kod under körning behövs.
"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"
]
}
}
},
Din agentkod skulle se ut ungefär så här:
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
}
}
I JavaScript, definiera en OBO-anslutning i anslutningsavbildningen och referera den från hanteraren med oboConnectionName och 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
Din agentkod skulle se ut ungefär så här:
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
}
}
I Python, definiera en OBO-anslutning under CONNECTIONS och referera den från hanteraren med OBOCONNECTIONNAME och 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
Din agentkod skulle se ut ungefär så här:
@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
OBO-utbyte under körning
Använd en runtime-exchange när du inte kan fixa nedströmsresursen, scopes eller anslutningen i konfigurationen. Denna situation uppstår till exempel när scopes beror på hyresgäst, användarroll eller en funktionsflagga. I denna modell konfigurerar du valfritt OBO-anslutningen och anropar sedan utbytesmetoden med de scopes du väljer vid turtillfället. Du får en utbytt token som du omedelbart kan använda.
Anropa ExchangeTurnTokenAsync med de scopes du väljer vid turtillfället.
"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"
]
}
}
},
Din agentkod skulle se ut ungefär så här:
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
}
}
Anropa authorization.exchangeToken med det hanterarnamn och de omfång du väljer vid turtillfället.
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
Din agentkod skulle se ut ungefär så här:
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
}
}
Anropa auth.exchange_token med de omfång du väljer vid turtillfället och hanterarnamnet.
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
Din agentkod skulle se ut ungefär så här:
@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
Regionala OAuth-inställningar
För icke-USA-regioner, uppdatera slutpunkten för token-tjänsten som din agent använder.
I exemplet nedan visas ett .NET-konfigurationen. Lägg till det i appsettings.json:
"RestChannelServiceClientFactory": {
"TokenServiceEndpoint": "{{service-endpoint-uri}}"
}
För service-endpoint-url använder du lämpligt värde från följande tabell för publika molnrobotar med dataresidens i den angivna regionen.
| URI | Region |
|---|---|
https://europe.api.botframework.com |
Europa |
https://unitedstates.api.botframework.com |
USA |
https://india.api.botframework.com |
Indien |