🔒 User Authentication
At times agents must access secured online resources on behalf of the user, such as checking email, checking on flight status, or placing an order. To enable this, the user must authenticate their identity and grant consent for the application to access these resources. This process results in the application receiving a token, which the application can then use to access the permitted resources on the user's behalf.
This is an advanced guide. It is highly recommended that you are familiar with Teams Core Concepts before attempting this guide.
User authentication does not work with the developer tools setup. You have to run the app in Teams. Follow these instructions to run your app in Teams.
It is possible to authenticate the user into other auth providers like Facebook, Github, Google, Dropbox, and so on.
Once you have configured your Azure Bot resource OAuth settings, as described in the official documentation, add the following code to your App:
Project Setup​
Create an app with the graph template​
Skip this step if you want to add the auth configurations to an existing app.
Use your terminal to run the following command:
npx @microsoft/teams.cli@latest new typescript oauth-app --template graph
This command:
- Creates a new directory called
oauth-app. - Bootstraps the graph agent template files into it under
oauth-app/src. - Creates your agent's manifest files, including a
manifest.jsonfile and placeholder icons in theoauth-app/appPackagedirectory.
Add Agents Toolkit auth configuration​
Open your terminal with the project folder set as the current working directory and run the following command:
npx @microsoft/teams.cli config add atk.oauth
The atk.oauth configuration is a basic setup for Agents Toolkit along with configurations to authenticate the user with Microsoft Entra ID to access Microsoft Graph APIs.
This CLI command adds configuration files required by Agents Toolkit, including:
- Azure Application Entra ID manifest file
aad.manifest.json. - Azure bicep files to provision Azure bot in
infra/folder.
Agents Toolkit, in the debugging flow, will deploy the aad.manifest.json and infra/azure.local.bicep file to provision the Application Entra ID and Azure bot with oauth configurations.
Configure the OAuth connection​
import { App } from '@microsoft/teams.apps';
import * as endpoints from '@microsoft/teams.graph-endpoints';
const app = new App({
oauth: {
defaultConnectionName: 'graph',
},
});
Make sure you use the same name you used when creating the OAuth connection in the Azure Bot Service resource.
In many templates, graph is the default name of the OAuth connection, but you can change that by supplying a different connection name in your app configuration.
Signing In​
This uses the Single Sign-On (SSO) authentication flow. To learn more about all the available flows and their differences see the official documentation.
You must call the signin method inside your route handler, for example: to signin when receiving the /signin message:
app.message('/signin', async ({ send, signin, isSignedIn }) => {
if (isSignedIn) {
send('you are already signed in!');
} else {
await signin();
}
});
Subscribe to the SignIn event​
You can subscribe to the signin event, that will be triggered once the OAuth flow completes.
app.event('signin', async ({ send, token }) => {
await send(
`Signed in using OAuth connection ${token.connectionName}. Please type **/whoami** to see your profile or **/signout** to sign out.`
);
});
Start using the graph client​
From this point, you can use the IsSignedIn flag and the userGraph client to query graph, for example to reply to the /whoami message, or in any other route.
The default OAuth configuration requests the User.ReadBasic.All permission. It is possible to request other permissions by modifying the App Registration for the bot on Azure.
import * as endpoints from '@microsoft/teams.graph-endpoints';
app.message('/whoami', async ({ send, userGraph, isSignedIn }) => {
if (!isSignedIn) {
await send('you are not signed in! please type **/signin** to sign in.');
return;
}
const me = await userGraph.call(endpoints.me.get);
await send(
`you are signed in as "${me.displayName}" and your email is "${me.mail || me.userPrincipalName}"`
);
});
app.on('message', async ({ send, activity, isSignedIn }) => {
if (isSignedIn) {
await send(
`You said: "${activity.text}". Please type **/whoami** to see your profile or **/signout** to sign out.`
);
} else {
await send(`You said: "${activity.text}". Please type **/signin** to sign in.`);
}
});
Signing Out​
You can signout by calling the signout method, this will remove the token from the User Token service cache
app.message('/signout', async ({ send, signout, isSignedIn }) => {
if (!isSignedIn) {
await send('you are not signed in! please type **/signin** to sign in.');
return;
}
await signout(); // call signout for your auth connection...
await send('you have been signed out!');
});