Microsoft Teams provides single sign-on (SSO) function for an app to obtain signed in Teams user token to access Microsoft Graph and other APIs. Microsoft 365 Agents Toolkit (previously known as Teams Toolkit) streamlines the process by incorporating certain Microsoft Entra workflows and integrations into straightforward, high-level APIs. As a result, you can effortlessly incorporate SSO capabilities into your Teams app. For more information, see authenticate users in Microsoft Teams.
Key configurations
To enable SSO, configure your Teams app as follows:
Microsoft Entra app manifest: Ensure to define URIs, including the URI that identifies the Microsoft Entra authentication app and the redirect URI that returns the token.
Teams app manifest: Connect your SSO app to your Teams app by incorporating the correct configuration.
Agents Toolkit configuration and infra files: Ensure the necessary configurations are in place to enable SSO for your Teams app.
SSO app information in Agents Toolkit configuration files: Ensure the authentication app registers on the backend service and Agents Toolkit initiates it during the debugging or previewing of the Teams app.
Create Microsoft Entra app manifest
Download the Microsoft Entra app manifest template.
Add the downloaded app manifest template code to ./aad.manifest.json
file. This allows you to customize different aspects of your app registration and update the manifest as required. For more information, see app manifest.
Update Teams app manifest
In the ./appPackages/manifest.json
file, add the following code:
"webApplicationInfo": {
"id": "${{AAD_APP_CLIENT_ID}}",
"resource": "api://${{TAB_DOMAIN}}/${{AAD_APP_CLIENT_ID}}"
}
webApplicationInfo
provides your Microsoft Entra App ID and Microsoft Graph information to assist users sign in to your app.
Note
You can use {{ENV_NAME}}
to reference variables in env/.env.{TEAMSFX_ENV}
file.
Locate your Agents Toolkit configuration files, such as ./m365agents.yml
and ./m365agents.local.yml
. Update the required configurations related to Microsoft Entra in these files.
Add the aadApp/create
action under provision
in ./m365agents.yml
and ./m365agents.local.yml
to create new Microsoft Entra app used for SSO:
- 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
Note
Replace the name
value with the desired name for your Teams app.
For more information, see aadApp/create
.
Add the aadApp/update
action under provision
in ./m365agents.yml
and ./m365agents.local.yml
to update your Microsoft Entra app:
- uses: aadApp/update
with:
manifestPath: "./aad.manifest.json"
outputFilePath: "./build/aad.manifest.${{TEAMSFX_ENV}}.json"
Note
- Update the
manifestPath
value to the relative path of the Microsoft Entra app manifest template aad.manifest.json
, if you've changed the file's path.
- In a local setup, position the
aad/update
after the file/createOrUpdateEnvironmentFile
action. This is required because aad/update
uses the output from file/createOrUpdateEnvironmentFile
.
For more information, see aadApp/update
For a React project, update cli/runNpmCommand
under deploy
.
If you're building a tab app using the React framework in CLI, find the cli/runNpmCommand
action with build app
in the m365agents.yml
file and add the following environment variables:
env:
REACT_APP_CLIENT_ID: ${{AAD_APP_CLIENT_ID}}
REACT_APP_START_LOGIN_PAGE_URL: ${{TAB_ENDPOINT}}/auth-start.html
If you're building a tab app with React framework, find the file/createOrUpdateEnvironmentFile
action for deployment in m365agents.local.yml
file and add the following environment variables:
envs:
...
REACT_APP_CLIENT_ID: ${{AAD_APP_CLIENT_ID}}
REACT_APP_START_LOGIN_PAGE_URL: ${{TAB_ENDPOINT}}/auth-start.html
Update source code
With the above changes implemented, your environment is prepared. You can now update your code to incorporate SSO into your Teams app.
Vanilla JavaScript
For a tab app that doesn't uses React, use the following code as a basic example to obtain the SSO token:
function getSSOToken() {
return new Promise((resolve, reject) => {
microsoftTeams.authentication.getAuthToken()
.then((token) => resolve(token))
.catch((error) => reject("Error getting token: " + error));
});
}
function getBasicUserInfo() {
getSSOToken().then((ssoToken) => {
const tokenObj = JSON.parse(window.atob(ssoToken.split(".")[1]));
console.log(`username: ${tokenObj.name}`);
console.log(`user email: ${tokenObj.preferred_username}`);
});
}
React
For React projects, ensure the following environment variables are set in your deployment process:
To update your source code, follow these steps:
Move the auth-start.html
and auth-end.html
files from the auth/public
folder to the public/
folder. These HTML files serve the purpose of handling authentication redirects.
Move sso
folder under auth/
to src/sso/
.
InitTeamsFx
: This file executes a function that initializes the TeamsFx SDK. After the SDK initialization, it opens the GetUserProfile
component.
GetUserProfile
: This file executes a function to retrieve user information by invoking the Microsoft Graph API.
Import and add InitTeamsFx
in Welcome.*
.
For more information, see SSO enabled tab app.
Create Microsoft Entra app manifest
Download the Microsoft Entra app manifest template.
Add the downloaded app manifest template code to ./aad.manifest.json
file. This allows you to customize different aspects of your app registration and update the manifest as required. For more information, see app manifest.
Update Teams app manifest
In the ./appPackages/manifest.json
file, add the following code:
"webApplicationInfo": {
"id": "${{AAD_APP_CLIENT_ID}}",
"resource": "api://${{TAB_DOMAIN}}/${{AAD_APP_CLIENT_ID}}"
}
webApplicationInfo
provides your Microsoft Entra App ID and Microsoft Graph information to assist users sign in to your app.
Note
You can use {{ENV_NAME}}
to reference variables in env/.env.{TEAMSFX_ENV}
file.
Register one or more commands in commandLists
.
The commandLists
includes commands that your bot can suggest to users. If you're using the teamsFx
bot template, set the following values:
{
"title": "profile",
"description": "Show user profile using Single Sign On feature"
}
The validDomains
field includes the domains for websites that the app loads within the Teams client. Update the following value:
"validDomains": [
"${{BOT_DOMAIN}}"
]
Locate your Agents Toolkit configuration files, such as ./m365agents.yml
and ./m365agents.local.yml
. Update necessary configurations related to Microsoft Entra in these files.
Add the following code aadApp/create
under provision
in ./m365agents.yml
and ./m365agents.local.yml
to create new Microsoft Entra apps used for SSO:
- 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
Note
Replace the name
value with the desired name for your Microsoft Teams app.
For more information, see aadApp/create
.
Add the following code aadApp/update
under provision
in ./m365agents.yml
and ./m365agents.local.yml
to update your Microsoft Entra app:
- uses: aadApp/update
with:
manifestPath: "./aad.manifest.json"
outputFilePath: "./build/aad.manifest.${{TEAMSFX_ENV}}.json"
Note
Update the manifestPath
value to the relative path of the Microsoft Entra app manifest template aad.manifest.json
, if you've changed the file's path.
For more information, see aadApp/update
Locate the createOrUpdateEnvironmentFile
action in m365agents.local.yml
file and add the following environment variables:
envs:
...
M365_CLIENT_ID: ${{AAD_APP_CLIENT_ID}}
M365_CLIENT_SECRET: ${{SECRET_AAD_APP_CLIENT_SECRET}}
M365_TENANT_ID: ${{AAD_APP_TENANT_ID}}
INITIATE_LOGIN_ENDPOINT: ${{BOT_ENDPOINT}}/auth-start.html
M365_AUTHORITY_HOST: ${{AAD_APP_OAUTH_AUTHORITY_HOST}}
M365_APPLICATION_ID_URI: api://botid-${{BOT_ID}}
Update Infra
Update Microsoft Entra-related configurations in your remote service. The following example shows the configuration settings on an Azure Web App:
M365_CLIENT_ID
: Microsoft Entra app client ID
M365_CLIENT_SECRET
: Microsoft Entra app client secret
M365_TENANT_ID
: Tenant ID of Microsoft Entra app
INITIATE_LOGIN_ENDPOINT
: Login start page for authentication
M365_AUTHORITY_HOST
: Microsoft Entra app OAuth authority host
M365_APPLICATION_ID_URI
: Identifier URI for Microsoft Entra app
To use the teamsFx
tab or bot template, follow these steps:
Open the infra/azure.parameters.json
file and add the following code:
"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}}"
}
Open infra/azure.bicep
file and add the following code after param location string = resourceGroup().location
:
param m365ClientId string
param m365TenantId string
param m365OauthAuthorityHost string
param m365ApplicationIdUri string = 'api://botid-${botAadAppClientId}'
@secure()
param m365ClientSecret string
Add the following code before output
in the infra/azure.bicep
file:
resource webAppSettings 'Microsoft.Web/sites/config@2021-02-01' = {
name: '${webAppName}/appsettings'
properties: {
M365_CLIENT_ID: m365ClientId
M365_CLIENT_SECRET: m365ClientSecret
INITIATE_LOGIN_ENDPOINT: uri('https://${webApp.properties.defaultHostName}', 'auth-start.html')
M365_AUTHORITY_HOST: m365OauthAuthorityHost
M365_TENANT_ID: m365TenantId
M365_APPLICATION_ID_URI: m365ApplicationIdUri
BOT_ID: botAadAppClientId
BOT_PASSWORD: botAadAppClientSecret
RUNNING_ON_AZURE: '1'
}
}
Note
- To add additional configurations into your Azure Web App, add the configurations in the
webAppSettings
.
- You might also need to define the default node version by adding the following configuration:
bash WEBSITE_NODE_DEFAULT_VERSION: '14.20.0'
Update Source Code
Move the files located in the auth/sso
folder to src
. The ProfileSsoCommandHandler
class serves as an SSO command handler, designed to retrieve user information using an SSO token. You can adopt this method to develop your own SSO command handler.
Move the auth/public
folder to src/public
. This folder contains HTML pages for the bot app. On initiating SSO flows with Microsoft Entra, the user is redirected to these pages.
Run the following command in ./
folder:
npm install copyfiles --save-dev
Update the following command in package.json
file:
"build": "tsc --build && shx cp -r ./src/adaptiveCards ./lib/src && copyfiles src/public/*.html lib/",
The HTML pages used for auth redirect are copied when building this bot project.
In src/index
file, add the following command to import isomorphic-fetch
:
require("isomorphic-fetch");
Add the following command to redirect to auth pages:
server.get(
"/auth-:name(start|end).html",
restify.plugins.serveStatic({
directory: path.join(__dirname, "public"),
})
);
Update commandApp.requestHandler
to ensure auth works with the following code:
await commandApp.requestHandler(req, res).catch((err) => {
// Error message including "412" means it is waiting for user's consent, which is a normal process of SSO, sholdn't throw this error.
if (!err.message.includes("412")) {
throw err;
}
});
Add ssoConfig
and ssoCommands
in ConversationBot
in src/internal/initialize
:
import { ProfileSsoCommandHandler } from "../profileSsoCommandHandler";
export const commandBot = new ConversationBot({
...
// To learn more about ssoConfig, please refer atk sdk document: https://docs.microsoft.com/microsoftteams/platform/toolkit/teamsfx-sdk
ssoConfig: {
aad :{
scopes:["User.Read"],
},
},
command: {
enabled: true,
commands: [new HelloWorldCommandHandler() ],
ssoCommands: [new ProfileSsoCommandHandler()],
},
});
Implement the API key handleMessageExtensionQueryWithSSO
in TeamsActivityHandler.handleTeamsMessagingExtensionQuery
. For more information, see SSO for message extensions.
Move the auth/public
folder to src/public
. This folder contains HTML pages for the bot app. On initiating SSO flows with Microsoft Entra, the user is redirected to these pages.
Update your src/index
file to add the appropriate restify
:
const path = require("path");
// Listen for incoming requests.
server.post("/api/messages", async (req, res) => {
await adapter.process(req, res, async (context) => {
await bot.run(context);
}).catch((err) => {
// Error message including "412" means it is waiting for user's consent, which is a normal process of SSO, sholdn't throw this error.
if(!err.message.includes("412")) {
throw err;
}
})
});
server.get(
"/auth-:name(start|end).html",
restify.plugins.serveStatic({
directory: path.join(__dirname, "public"),
})
);
Run the following commands under ./
folder:
npm install @microsoft/atk
npm install isomorphic-fetch
Implement the API key handleMessageExtensionQueryWithSSO
in TeamsActivityHandler.handleTeamsMessagingExtensionQuery
.
Install copyfiles
npm packages in your TypeScript bot project and update the build
script in src/package.json
file as follows:
"build": "tsc --build && copyfiles ./public/*.html lib/",
The HTML pages used for auth redirect are copied when building this bot project.
Update templates/appPackage/aad.template.json
file with the scopes you use in the handleMessageExtensionQueryWithSSO
function:
"requiredResourceAccess": [
{
"resourceAppId": "Microsoft Graph",
"resourceAccess": [
{
"id": "User.Read",
"type": "Scope"
}
]
}
]
Debug your app
To debug your app, select the F5 key. Agents Toolkit uses the Microsoft Entra manifest to register an SSO-enabled app. For more information, see debug your Teams app locally.
Customize Microsoft Entra apps
Teams app manifest enables you to customize different aspects of your app registration. You can update the manifest as required.
To include additional API permissions to access your desired APIs, see edit Microsoft Entra manifest.
To view your Microsoft Entra app in Azure portal, see edit Microsoft Entra manifest.
See also