Microsoft Teams 为应用提供单一登录 (SSO) 函数,以获取已登录的 Teams 用户令牌,以访问 Microsoft Graph 和其他 API。 Microsoft 365 代理工具包 (以前称为 Teams 工具包) 通过抽象化一些简单 API 背后的一些Microsoft Entra ID流和集成来促进交互。 这使你可以轻松地将 SSO 功能添加到 Teams 应用。
在 Visual Studio 代理工具包中启用 SSO
Teams 使用适用于 Microsoft Visual Studio 的 Agents Toolkit 为应用提供 SSO 功能。
打开 Visual Studio。
选择 “项目>Microsoft 365 代理工具包>添加身份验证代码”。
代理工具包可帮助你在 TeamsFx-Auth 文件夹中生成身份验证文件,包括应用清单 (以前称为 Teams 应用清单) 模板文件,用于Microsoft Entra应用程序和身份验证重定向页面。 通过更新身份验证配置将文件链接到 Teams 应用程序,以确保 SSO 适用于应用程序。
- 在 Microsoft Entra 应用清单文件中,指定统一资源标识符 (URI) 例如用于标识Microsoft Entra身份验证应用的 URI 和用于返回令牌的重定向 URI。
- 在应用清单文件中,添加 SSO 应用程序以将其与 Teams 应用程序链接。
- 在代理工具包配置文件中添加 SSO 应用程序信息,以确保可以在后端服务上注册身份验证应用,并在调试或预览 Teams 应用程序时启动代理工具包。
Teams 选项卡应用程序
更新Microsoft Entra应用清单:
TeamsFx-Auth/aad.manifest.template.json
文件是Microsoft Entra应用清单模板。 可以将此文件复制并粘贴到项目的任何文件夹,并重命名为aad.manifest.json
并记下此文件的路径。 模板中的以下更新,用于创建/更新用于 SSO 的 Microsoft Entra 应用:identifierUris
:它用于唯一标识和访问资源。 将正确的重定向 URI 设置为 以identifierUris
成功标识此应用。 有关详细信息,请参阅 identifierUris 属性。"identifierUris":[ "api://${{TAB_DOMAIN}}/${{AAD_APP_CLIENT_ID}}" ]
redirectUris
:它列出了在返回令牌时Microsoft Entra ID接受作为目标的已注册redirect_uri值。 将必要的重定向 URI 设置为redirectUris
以成功返回令牌。 有关详细信息,请参阅 redirectUris 属性。"web": { "redirectUris": [ "${{TAB_ENDPOINT}}/auth-end.html" ] }
注意
使用
${{ENV_NAME}}
引用 中的env/.env.{TEAMSFX_ENV}
变量。"web": { "redirectUris": [ "${{TAB_ENDPOINT}}/auth-end.html" ] }, "spa": { "redirectUris": [ "${{TAB_ENDPOINT}}/auth-end.html?clientId=${{AAD_APP_CLIENT_ID}}", "${{TAB_ENDPOINT}}/blank-auth-end.html" ] }
“name”:它将值替换为预期的Microsoft Entra应用名称。
打开应用清单文件,添加
WebApplicationInfo
具有 SSO 应用值的 属性。 有关详细信息,请参阅 webApplicationInfo。"webApplicationInfo": { "id": "${{AAD_APP_CLIENT_ID}}", "resource": "SAME_AS_YOUR_IDENTIFIERURIS" }
注意
将资源的值更新为
identifierUris
步骤 1 中配置的 ,并使用${{ENV_NAME}}
引用 中的env/.env.{TEAMSFX_ENV}
envs。打开 文件
appPackage/manifest.json
,并添加以下代码:"webApplicationInfo": { "id": "${{AAD_APP_CLIENT_ID}}", "resource": "api://${{TAB_DOMAIN}}/${{AAD_APP_CLIENT_ID}}" }
m365agents.yml
更新文件和m365agents.local.yml
文件。将Microsoft Entra相关更改和配置添加到文件中
yml
:在“创建用于 SSO 的新Microsoft Entra应用”下
provision
添加aadApp/create
。 有关详细信息,请参阅 aadApp/create。注意
可以直接在 .yml 文件下
writeToEnvironmentFile
添加任何缺少的参数。添加
aadApp/update
:provision
在步骤 1 中使用Microsoft Entra应用清单更新Microsoft Entra应用。 有关详细信息,请参阅 aadApp/update。更新
file/createOrUpdateJsonFile
:在本地调试时添加以下环境变量:- ClientId:Microsoft Entra应用客户端 ID。
- ClientSecret:Microsoft Entra应用客户端密码。
- OAuthAuthority:Microsoft Entra应用 oauth 机构。
有关详细信息,请参阅 file/updateJson。
在
m365agents.yml
文件和m365agents.local.yml
文件中,在 下provision
添加以下代码,以创建 Microsoft Entra 应用。- uses: aadApp/create with: name: "YOUR_AAD_APP_NAME" generateClientSecret: true signInAudience: "AzureADMyOrg" writeToEnvironmentFile: clientId: AAD_APP_CLIENT_ID clientSecret: SECRET_AAD_APP_CLIENT_SECRET objectId: AAD_APP_OBJECT_ID tenantId: AAD_APP_TENANT_ID authority: AAD_APP_OAUTH_AUTHORITY authorityHost: AAD_APP_OAUTH_AUTHORITY_HOST
注意
将“name”值替换为预期的Microsoft Entra应用名称。
在
provision
下添加以下行,以在步骤 1 中使用Microsoft Entra应用模板配置Microsoft Entra应用。- uses: aadApp/update with: manifestPath: "YOUR_PATH_TO_AAD_APP_MANIFEST" outputFilePath : ./build/aad.manifest.${{TEAMSFX_ENV}}.json
注意
将 的值
manifestPath
替换为步骤 1 中记录的Microsoft Entra应用清单的相对路径。 例如:./aad.manifest.json
m365agents.local.yml
在 文件中:在 下
provision
添加以下代码,将Microsoft Entra相关配置添加到本地调试服务。注意
file/createOrUpdateJsonFile
如果在 中m365agents.local.yml
配置了 节,则可以跳过以下步骤。- uses: file/createOrUpdateJsonFile with: target: ./appsettings.Development.json appsettings: TeamsFx: Authentication: ClientId: ${{AAD_APP_CLIENT_ID}} ClientSecret: ${{SECRET_AAD_APP_CLIENT_SECRET}} InitiateLoginEndpoint: ${{TAB_ENDPOINT}}/auth-start.html OAuthAuthority: ${{AAD_APP_OAUTH_AUTHORITY}}
更新 Infra Microsoft Entra 相关配置需要在远程服务中配置。 以下示例演示 Azure Webapp 上的配置。
- TeamsFx__Authentication__ClientId:Microsoft Entra应用客户端 ID。
- TeamsFx__Authentication__ClientSecret:Microsoft Entra应用客户端密码。
- TeamsFx__Authentication__OAuthAuthority:Microsoft Entra应用 oauth 机构。
TeamsFx 选项卡模板的示例。
打开
infra/azure.parameters.json
以下行并将其添加到 中parameters
:"tabAadAppClientId": { "value": "${{AAD_APP_CLIENT_ID}}" }, "tabAadAppClientSecret": { "value": "${{SECRET_AAD_APP_CLIENT_SECRET}}" }, "tabAadAppOauthAuthorityHost": { "value": "${{AAD_APP_OAUTH_AUTHORITY_HOST}}" }, "tabAadAppTenantId": { "value": "${{AAD_APP_TENANT_ID}}" }
infra/azure.bicep
打开 文件,找到代码:param location string = resourceGroup().location
将代码更新为:
param tabAadAppClientId string param tabAadAppOauthAuthorityHost string param tabAadAppTenantId string @secure() param tabAadAppClientSecret string
在
infra/azure.bicep
文件中,找到代码:resource webApp 'Microsoft.Web/sites@2021-02-01' = { kind: 'app' location: location name: webAppName properties: { serverFarmId: serverfarm.id httpsOnly: true siteConfig: { appSettings: [ { name: 'WEBSITE_RUN_FROM_PACKAGE' value: '1' } ] ftpsState: 'FtpsOnly' } } }
将代码更新为:
resource webApp 'Microsoft.Web/sites@2021-02-01' = { kind: 'app' location: location name: webAppName properties: { serverFarmId: serverfarm.id httpsOnly: true siteConfig: { ftpsState: 'FtpsOnly' } } } resource webAppConfig 'Microsoft.Web/sites/config@2021-02-01' = { name: '${webAppName}/appsettings' properties: { WEBSITE_RUN_FROM_PACKAGE: '1' TeamsFx__Authentication__ClientId: tabAadAppClientId TeamsFx__Authentication__ClientSecret: tabAadAppClientSecret TeamsFx__Authentication__InitiateLoginEndpoint: 'https://${webApp.properties.defaultHostName}/auth-start.html' TeamsFx__Authentication__OAuthAuthority: uri(tabAadAppOauthAuthorityHost, tabAadAppTenantId) } }
需要针对 .NET 项目设置配置Microsoft Entra相关配置的更新
appsettings.json
和appsettings.Development.json
文件:TeamsFx: { Authentication: { ClientId: AAD app client id ClientSecret: AAD app client secret, InitiateLoginEndpoint: Login Endpoint, OAuthAuthority: AAD app oauth authority } }
注意
可以使用
$ENV_NAME$
在本地/远程服务中引用 envs。TeamsFx 选项卡模板的示例。
打开
appsettings.json
和appsettings.Development.json
文件,并更新代码:"TeamsFx": { "Authentication": { "ClientId": "$clientId$", "ClientSecret": "$client-secret$", "InitiateLoginEndpoint": "$TAB_ENDPOINT$/auth-start.html", "OAuthAuthority": "$oauthAuthority$" } }
你的环境已准备就绪,可以更新代码以将 SSO 添加到 Teams 应用。 可找到示例:
- TeamsFx SDK: https://www.nuget.org/packages/Microsoft.TeamsFx/
- 示例代码:下
TeamsFx-Auth/Tab
TeamsFx 选项卡模板的示例。
创建
Config.cs
并更新代码,如下所示:using Microsoft.TeamsFx.Configuration; namespace {{YOUR_NAMESPACE}} { public class ConfigOptions { public TeamsFxOptions TeamsFx { get; set; } } public class TeamsFxOptions { public AuthenticationOptions Authentication { get; set; } } }
注意
需要将 替换为
{{YOUR_NAMESPACE}}
命名空间名称。将
TeamsFx-Auth/Tab/GetUserProfile.razor
文件移动到Components/
。将
GetUserProfile
组件添加到 razor 页面,例如:<h1>Hello, World</h1> <GetUserProfile />
Program.cs
打开 文件,找到代码:builder.Services.AddScoped<MicrosoftTeams>();
并将代码更新为:
var config = builder.Configuration.Get<ConfigOptions>(); builder.Services.AddTeamsFx(config.TeamsFx.Authentication); ```
注意
需要通过将以下代码添加到 文件来排除文件下
TeamsFx-Auth
的示例代码.csproj
,以避免生成失败:<ItemGroup> <Compile Remove="TeamsFx-Auth/**/*" /> <None Include="TeamsFx-Auth/**/*" /> <Content Remove="TeamsFx-Auth/Tab/GetUserProfile.razor"/> </ItemGroup> ``` * Download `auth-start.html` and `auth-end.html` files from [GitHub Repo](https://github.com/OfficeDev/TeamsFx/tree/dev/templates/csharp/sso-tab/wwwroot) to `{ProjectDirectory}/wwwroot`.
若要检查 SSO 应用按预期工作,请在 Visual Studio 中运行
Local Debug
。还可以通过依次选择
Provision in the cloud
和Deploy to the cloud
在云中运行应用。
Teams 机器人应用程序
更新文件中Microsoft Entra应用清单
TeamsFx-Auth/aad.manifest.template.json
。可以将文件复制到项目的任何文件夹,并重命名为
aad.manifest.json
文件,并记下此文件的路径以供以后参考。 在模板中进行以下更新,以创建或更新用于 SSO 的 Microsoft Entra 应用。-
identifierUris
:用于唯一标识和访问资源。 需要将正确的重定向 URI 设置为“identifierUris”才能成功标识此应用。 有关详细信息,请参阅 identifierUris 属性。
TeamsFx 机器人模板的示例:
"identifierUris":[ "api://botid-${{BOT_ID}}" ]
注意
可以使用
${{ENV_NAME}}
引用 文件中的env/.env.{TEAMSFX_ENV}
变量。-
redirectUris
:它列出了在返回令牌时Microsoft Entra ID接受作为目标的已注册redirect_uri值。 需要将必要的重定向 URI 设置为“redirectUris”才能成功返回令牌。 有关详细信息,请参阅 redirectUris 属性。
示例:
"web": { "redirectUris": [ "https://${{BOT_DOMAIN}}/bot-auth-end.html" ] }
- “name”:将值替换为预期的Microsoft Entra应用名称。
-
更新应用清单。
-
WebApplicationInfo
需要将 对象添加到应用清单中,才能在 Teams 应用中启用 SSO。 有关详细信息,请参阅 webApplicationInfo。
例如:打开应用清单模板,并在应用清单中追加以下对象:
"webApplicationInfo": { "id": "${{AAD_APP_CLIENT_ID}}", "resource": "SAME_AS_YOUR_IDENTIFIERURIS" }
注意
需要将资源的值更新到
identifierUris
步骤 1.i 中配置的 ,并使用${{ENV_NAME}}
引用 中的env/.env.{TEAMSFX_ENV}
envs。TeamsFx 机器人模板的示例:
appPackage/manifest.json
打开 文件,并在应用清单文件中添加以下属性:"webApplicationInfo": { "id": "${{AAD_APP_CLIENT_ID}}", "resource": "api://botid-${{BOT_ID}}" }
- 可以在机器人中
commands
commandLists
注册命令:
{ "title": "YOUR_COMMAND_TITLE", "description": "YOUR_COMMAND_DESCRIPTION" }
TeamsFx 机器人模板的示例:
{ "title": "show", "description": "Show user profile using Single Sign On feature" }
请记住删除以前的“helloWorld”命令,因为它未使用。
- 此外,将机器人域添加到
validDomain
:
"validDomains": [ "${{BOT_DOMAIN}}" ]
-
更新
m365agents.yml
和m365agents.local.yml
文件:Microsoft Entra相关更改和配置需要添加到文件中yml
:在 下
provision
添加aadApp/create
,以创建新的Microsoft Entra用于 SSO 的应用。 有关详细信息,请参阅 代理工具包中的可用作。注意
可以直接在 .yml 文件下
writeToEnvironmentFile
添加任何缺少的参数。provision
在aadApp/update
步骤 1 中使用Microsoft Entra应用清单来更新Microsoft Entra应用。 有关详细信息,请参阅 aadApp/update。更新
file/createOrUpdateJson
文件,以便在本地调试期间添加以下环境变量:- ClientId:Microsoft Entra应用客户端 ID。
- ClientSecret:Microsoft Entra应用客户端密码。
- OAuthAuthority:Microsoft Entra应用 oauth 机构。 有关详细信息,请参阅 file/updateJson。
TeamsFx 机器人模板的示例
m365agents.yml
在 和m365agents.local.yml
文件中:在 下
provision
添加代码以创建Microsoft Entra应用。注意
aadApp/create
如果 .yml 文件中的下面provision
缺少该节,则可以将所需的部分复制并粘贴到其中。
- uses: aadApp/create with: name: "YOUR_AAD_APP_NAME" generateClientSecret: true signInAudience: "AzureADMyOrg" writeToEnvironmentFile: clientId: AAD_APP_CLIENT_ID clientSecret: SECRET_AAD_APP_CLIENT_SECRET objectId: AAD_APP_OBJECT_ID tenantId: AAD_APP_TENANT_ID authority: AAD_APP_OAUTH_AUTHORITY authorityHost: AAD_APP_OAUTH_AUTHORITY_HOST
注意
将“name”值替换为预期的Microsoft Entra应用名称。
在 下
provision
添加代码,以在步骤 1 中使用Microsoft Entra应用模板配置Microsoft Entra应用。- uses: aadApp/update with: manifestPath: "./aad.manifest.json" outputFilePath : ./build/aad.manifest.${{TEAMSFX_ENV}}.json
注意
将“manifestPath”的值替换为步骤 1 中记录的Microsoft Entra应用清单的相对路径。 例如,“./aad.manifest.json”
m365agents.local.yml
在 文件中:在 下
provision
更新file/createOrUpdateJsonFile
,将Microsoft Entra相关配置添加到本地调试服务。注意
file/createOrUpdateJsonFile
如果在 中m365agents.local.yml
配置了 节,则可以跳过以下步骤。- uses: file/createOrUpdateJsonFile with: target: ../ProjecName/appsettings.Development.json appsettings: BOT_ID: ${{BOT_ID}} BOT_PASSWORD: ${{SECRET_BOT_PASSWORD}} TeamsFx: Authentication: ClientId: ${{AAD_APP_CLIENT_ID}} ClientSecret: ${{SECRET_AAD_APP_CLIENT_SECRET}} OAuthAuthority: ${{AAD_APP_OAUTH_AUTHORITY}}/${{AAD_APP_TENANT_ID}} ApplicationIdUri: api://botid-${{BOT_ID}} Bot: InitiateLoginEndpoint: https://${{BOT_DOMAIN}}/bot-auth-start
更新 Infra Microsoft Entra相关配置以配置远程服务。 以下示例演示 Azure Webapp 上的配置。
- TeamsFx__Authentication__ClientId:Microsoft Entra应用客户端 ID。
- TeamsFx__Authentication__ClientSecret:Microsoft Entra应用客户端密码。
- TeamsFx__Authentication__OAuthAuthority:Microsoft Entra应用 oauth 机构。
- TeamsFx__Authentication__Bot__InitiateLoginEndpoint:机器人的身份验证起始页。
- TeamsFx__Authentication__ApplicationIdUri:Microsoft Entra应用标识 URI。
TeamsFx 机器人模板的示例:
infra/azure.parameters.json
打开 文件,将代码添加到parameters
:"m365ClientId": { "value": "${{AAD_APP_CLIENT_ID}}" }, "m365ClientSecret": { "value": "${{SECRET_AAD_APP_CLIENT_SECRET}}" }, "m365TenantId": { "value": "${{AAD_APP_TENANT_ID}}" }, "m365OauthAuthorityHost": { "value": "${{AAD_APP_OAUTH_AUTHORITY_HOST}}" }
infra/azure.bicep
打开 文件并查找代码:param location string = resourceGroup().location
将代码更新为:
param location string = resourceGroup().location param m365ClientId string param m365TenantId string param m365OauthAuthorityHost string param m365ApplicationIdUri string = 'api://botid-${botAadAppClientId}' @secure() param m365ClientSecret string
在输出前添加代码:
resource webAppSettings 'Microsoft.Web/sites/config@2021-02-01' = { name: '${webAppName}/appsettings' properties: { TeamsFx__Authentication__ClientId: m365ClientId TeamsFx__Authentication__ClientSecret: m365ClientSecret TeamsFx__Authentication__Bot__InitiateLoginEndpoint: uri('https://${webApp.properties.defaultHostName}', 'bot-auth-start') TeamsFx__Authentication__OAuthAuthority: uri(m365OauthAuthorityHost, m365TenantId) TeamsFx__Authentication__ApplicationIdUri: m365ApplicationIdUri BOT_ID: botAadAppClientId BOT_PASSWORD: botAadAppClientSecret RUNNING_ON_AZURE: '1' } }
注意
如果要将其他配置添加到 Azure Web 应用,请在 webAppSettings 中添加配置。
appsettings.json
appsettings.Development.json
更新文件和需要配置到 .NET 项目设置Microsoft Entra相关配置的文件:TeamsFx: { Authentication: { ClientId: AAD app client id ClientSecret: AAD app client secret, OAuthAuthority: AAD app oauth authority, ApplicationIdUri: AAD app identify uri, Bot: { InitiateLoginEndpoint: Auth start page for Bot } } }
注意
可以使用
$ENV_NAME$
在本地/远程服务中引用 envs。TeamsFx 机器人模板的示例:
打开
appsettings.json
和appsettings.Development.json
文件,并添加代码:"TeamsFx": { "Authentication": { "ClientId": "$clientId$", "ClientSecret": "$client-secret$", "OAuthAuthority": "$oauthAuthority$", "ApplicationIdUri": "$applicationIdUri$", "Bot": { "InitiateLoginEndpoint": "$initiateLoginEndpoint$" } } }
更新代码以将 SSO 添加到 Teams 应用。
可以找到示例代码:
- TeamsFx SDK: https://www.nuget.org/packages/Microsoft.TeamsFx/
- 示例代码:下
TeamsFx-Auth/Bot
TeamsFx 机器人模板的示例:
- 打开
Config.cs
以下类并将其添加到 命名空间:
using Microsoft.TeamsFx.Configuration; namespace {{YOUR_NAMESPACE}} { public class TeamsFxOptions { public AuthenticationOptions Authentication { get; set; } } public class ConfigOptions { public string BOT_ID { get; set; } public string BOT_PASSWORD { get; set; } public TeamsFxOptions TeamsFx { get; set; } } }
注意
将
{{YOUR_NAMESPACE}}
属性替换为命名空间名称。将 和
TeamsFx-Auth/Bot/Pages
文件移动到/
TeamsFx-Auth/Bot/SSO
。注意
请记住将 替换为
{{YOUR_NAMESPACE}}
项目命名空间。Program.cs
打开 文件,并找到代码:
builder.Services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();
将代码更新为:
builder.Services.AddRazorPages(); // Create the Bot Framework Adapter with error handling enabled. builder.Services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>(); builder.Services.AddSingleton<IStorage, MemoryStorage>(); // Create the Conversation state. (Used by the Dialog system itself.) builder.Services.AddSingleton<ConversationState>(); // The Dialog that will be run by the bot. builder.Services.AddSingleton<SsoDialog>(); // Create the bot as a transient. In this case the ASP Controller is expecting an IBot. builder.Services.AddTransient<IBot, TeamsSsoBot<SsoDialog>>(); builder.Services.AddOptions<BotAuthenticationOptions>().Configure(options => { options.ClientId = config.TeamsFx.Authentication.ClientId; options.ClientSecret = config.TeamsFx.Authentication.ClientSecret; options.OAuthAuthority = config.TeamsFx.Authentication.OAuthAuthority; options.ApplicationIdUri = config.TeamsFx.Authentication.ApplicationIdUri; options.InitiateLoginEndpoint = config.TeamsFx.Authentication.Bot.InitiateLoginEndpoint; });
查找代码:
builder.Services.AddSingleton<HelloWorldCommandHandler>(); builder.Services.AddSingleton(sp => { var options = new ConversationOptions() { Adapter = sp.GetService<CloudAdapter>(), Command = new CommandOptions() { Commands = new List<ITeamsCommandHandler> { sp.GetService<HelloWorldCommandHandler>() } } }; return new ConversationBot(options); });
将代码更新为:
builder.Services.AddSingleton(sp => { var options = new ConversationOptions() { Adapter = sp.GetService<CloudAdapter>(), Command = new CommandOptions() { Commands = new List<ITeamsCommandHandler> { } } }; return new ConversationBot(options); });
查找并删除代码:
// Create the bot as a transient. In this case the ASP Controller is expecting an IBot. builder.Services.AddTransient<IBot, TeamsBot>();
查找代码:
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
将代码更新为:
app.UseEndpoints(endpoints => { endpoints.MapControllers(); endpoints.MapRazorPages(); });
注意
需要通过将以下代码添加到文件来排除下
TeamsFx-Auth
的示例代码.csproj
,以避免生成失败:<ItemGroup> <Compile Remove="TeamsFx-Auth/**/*" /> <None Include="TeamsFx-Auth/**/*" /> <Content Remove="TeamsFx-Auth/Tab/GetUserProfile.razor"/> </ItemGroup>
若要检查 SSO 应用是否按预期工作,请在 Visual Studio 中运行
Local Debug
。还可以在云中运行应用,方法是选择
Provision in the cloud
,然后选择Deploy to the cloud
更新应用。