Add authentication to your Teams bot

There are times when you may need to create bots in Microsoft Teams that can access resources on behalf of the user, such as a mail service.

This article demonstrates how to use Azure Bot Service v4 SDK authentication, based on OAuth 2.0. This makes it easier to develop a bot that can use authentication tokens based on the user's credentials. Key in all this is the use of identity providers, as we will see later.

OAuth 2.0 is an open standard for authentication and authorization used by Azure Active Directory (Azure AD) and many other identity providers. A basic understanding of OAuth 2.0 is a prerequisite for working with authentication in Teams.

See OAuth 2 Simplified for a basic understanding, and OAuth 2.0 for the complete specification.

For more information about how the Azure Bot Service handles authentication, see User authentication within a conversation.

In this article you'll learn:

  • How to create an authentication-enabled bot. You'll use cs-auth-sample to handle user sign-in credentials and the generating the authentication token.
  • How to deploy the bot to Azure and associate it with an identity provider. The provider issues a token based on user sign-in credentials. The bot can use the token to access resources, such as a mail service, which require authentication. For more information see Microsoft Teams authentication flow for bots.
  • How to integrate the bot within Microsoft Teams. Once the bot has been integrated, you can sign in and exchange messages with it in a chat.

Prerequisites

Create the resource group

The resource group and the service plan aren't strictly necessary, but they allow you to conveniently release the resources you create. This is good practice for keeping your resources organized and manageable.

You use a resource group to create individual resources for the Bot Framework. For performance, ensure that these resources are located in the same Azure region.

  1. In your browser, sign into the Azure portal.
  2. In the left navigation panel, select Resource groups.
  3. In the upper left of the displayed window, select Add tab to create a new resource group. You'll be prompted to provide the following:
    1. Subscription. Use your existing subscription.
    2. Resource group. Enter the name for the resource group. An example could be TeamsResourceGroup. Remember that the name must be unique.
    3. From the Region drop-down menu, select West US, or a region close to your applications.
    4. Select the Review and create button. You should see a banner that reads Validation passed.
    5. Select the Create button. It may take a few minutes to create the resource group.

Tip

As with the resources you'll create later in this tutorial, it's a good idea to pin this resource group to your dashboard for easy access. If you'd like to do so, select the pin icon πŸ“Œ in the upper right of the dashboard.

Create the service plan

  1. In the Azure portal, on the left navigation panel, select Create a resource.
  2. In the search box, type App Service Plan. Select the App Service Plan card from the search results.
  3. Select Create.
  4. You'll be asked to provide the following information:
    1. Subscription. You can use an existing subscription.
    2. Resource Group. Select the group you created earlier.
    3. Name. Enter the name for the service plan. An example could be TeamsServicePlan. Remember that the name must be unique, within the group.
    4. Operating System. Select Windows or your applicable OS.
    5. Region. Select West US or a region close to your applications.
    6. Pricing Tier. Make sure that Standard S1 is selected. This should be the default value.
    7. Select the Review and create button. You should see a banner that reads Validation passed.
    8. Select Create. It may take a few minutes to create the app service plan. The plan will be listed in the resource group.

Create the bot channels registration

The bot channels registration registers your web service as a bot with the Bot Framework, provided you have a Microsoft App Id and App password (client secret).

Important

You only need to register your bot if it is not hosted in Azure. If you created a bot through the Azure portal then it is already registered with the service. If you created your bot through the Bot Framework or AppStudio your bot isn't registered in Azure.

  1. In the [Azure portal][azure-portal], on the left navigation panel, select Create a resource.

  2. In the right panel selection box enter "bot". And in the drop-down list, select Bot Channels Registration.

  3. Click the Create button.

  4. In the Bot Channel Registration blade, provide the requested information about your bot.

  5. Leave the Messaging endpoint box empty for now, you will enter the required URL after deploying the bot. The following picture shows an example of the registration settings:

    bot app channels registration

  6. Click Microsoft App ID and password and then Create New.

  7. Click Create App ID in the App Registration Portal link.

  8. In the displayed App registration window, click the New registration tab in the upper left.

  9. Enter the name of the bot application you are registering, we used BotTeamsAuth (you need to select your own unique name).

  10. For the Supported account types select Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox).

  11. Click the Register button. Once completed, Azure displays the Overview page for the application.

  12. Copy and save to a file the Application (client) ID value.

  13. In the left panel, click Certificate and secrets.

    1. Under Client secrets, click New client secret.
    2. Add a description to identify this secret from others you might need to create for this app.
    3. Set Expires to your selection.
    4. Click Add.
    5. Copy the client secret and save it to a file.
  14. Go back to the Bot Channel Registration window and copy the App ID and the Client secret in the Microsoft App ID and Password boxes, respectively.

  15. Click OK.

  16. Finally, click Create.

After Azure has created the registration resource it will be included in the resource group list.

bot app channels registration group

Note

The Bot Channels Registration resource will show the Global region even if you selected West US. This is expected.

For more information, see Create a bot for Teams.

Create the identity provider

You need an identity provider that can be used for authentication. In this procedure you'll use an Azure AD provider; other Azure AD supported identity providers can also be used.

  1. In the Azure portal, on the left navigation panel, select Azure Active Directory.

    Tip

    You'll need to create and register this Azure AD resource in a tenant in which you can consent to delegate permissions requested by an application. For instruction on creating a tenant, see Access the portal and create a tenant.

  2. In the left panel, select App registrations.

  3. In the right panel, select the New registration tab, in the upper left.

  4. You'll be asked to provide the following information:

    1. Name. Enter the name for the application. An example could be BotTeamsIdentity. Remember that the name must be unique.
    2. Select the Supported account types for your application. Select Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox).
    3. For the Redirect URI:
      βœ“Select Web.
      βœ“ Set the URL to https://token.botframework.com/.auth/web/redirect.
    4. Select Register.
  5. Once it is created, Azure displays the Overview page for the app. Copy and save the following information to a file:

    1. The Application (client) ID value. You'll use this value later as the Client ID when you register this Azure identity application with your bot.
    2. The Directory (tenant) ID value. You'll also use this value later as the Tenant ID to register this Azure identity application with your bot.
  6. In the left panel, select Certificates & secrets to create a client secret for your application.

    1. Under Client secrets, select βž• New client secret.
    2. Add a description to identify this secret from others you might need to create for this app, such as Bot identity app in Teams.
    3. Set Expires to your selection.
    4. Select Add.
    5. Before leaving this page, record the secret. You'll use this value later as the Client secret when you register your Azure AD application with your bot.

Configure the identity provider connection and register it with the bot

  1. In the Azure portal, select your resource group from the dashboard.

  2. Select your bot channel registration link.

  3. On the resource page, select Settings.

  4. Under OAuth Connection Settings near the bottom of the page, select Add Setting.

  5. Complete the form as follows:

    1. Name. Enter a name for the connection. You'll use this name in your bot in the appsettings.json file. For example BotTeamsAuthADv1.

    2. Service Provider. Select Azure Active Directory. Once you select this, the Azure AD-specific fields will be displayed.

    3. Client id. Enter the Application (client) ID that you recorded for your Azure identity provider app in the steps above.

    4. Client secret. Enter the secret that you recorded for your Azure identity provider app in the steps above.

    5. Grant Type. Enter authorization_code.

    6. Login URL. Enter https://login.microsoftonline.com.

    7. Tenant ID, enter the Directory (tenant) ID that you recorded earlier for your Azure identity app or common depending on the supported account type selected when you created the identity provider app. To decide which value to assign follow these criteria:

      • If you selected either Accounts in this organizational directory only (Microsoft only - Single tenant) or Accounts in any organizational directory(Microsoft AAD directory - Multi tenant) enter the tenant ID you recorded earlier for the AAD app. This will be the tenant associated with the users who can be authenticated.

      • If you selected Accounts in any organizational directory (Any AAD directory - Multi tenant and personal Microsoft accounts e.g. Skype, Xbox, Outlook) enter the word common instead of a tenant ID. Otherwise, the AAD app will verify through the tenant whose ID was selected and exclude personal Microsoft accounts.

    h. For Resource URL, enter https://graph.microsoft.com/. This is not used in the current code sample.
    i. Leave Scopes blank. The following image is an example:

    teams bots app auth connection string adv1

  6. Select Save.

Test the connection

  1. Select the connection entry to open the connection you just created.

  2. Select Test Connection at the top of the Service Provider Connection Setting panel.

  3. The first time you do this will open a new browser window asking you to select an account. Select the one you want to use.

  4. Next, you'll be asked to allow to the identity provider to use your data (credentials). The following image is an example:

    teams bots app auth connection string adv1

  5. Select Accept.

  6. This should then redirect you to a Test Connection to <your-connection-name> Succeeded page. Refresh the page if you get an error. The following image is an example:

teams bots app auth connection string adv1

The connection name is used by the bot code to retrieve user authentication tokens.

Prepare the bot sample code

With the preliminary settings done, let's focus on the creation of the bot to use in this article.

  1. Clone cs-auth-sample.

  2. Launch Visual Studio.

  3. From the toolbar select File -> Open -> Project/Solution and open the bot project.

  4. Update appsettings.json as follows:

    • Set ConnectionName to the name of the identity provider connection you added to the bot channel registration. The name we used in this example is BotTeamsAuthADv1.
    • Set MicrosoftAppId to the bot App ID you saved at the time of the bot channel registration.
    • Set MicrosoftAppPassword to the customer secret you saved at the time of the bot channel registration.
    • Set the ConnectionName to the name of the identity provider connection.

    Depending on the characters in your bot secret, you may need to XML escape the password. For example, any ampersands (&) will need to be encoded as &amp;.

     ```cs
     {
         "MicrosoftAppId": "", // The bot App Id 
         "MicrosoftAppPassword": "", // The bot client secret
         "ConnectionName": "" // The name of the identity provider connection
     }
     ```
    
  5. In the Solution Explorer, navigate to the TeamsAppManifest folder, open manifest.json and set id and botId to the bot App ID you saved at the time of the bot channel registration.

Deploy the bot to Azure

To deploy the bot, follow the steps in the how to Deploy your bot to Azure.

Alternatively, while in Visual Studio, you can follow these steps:

  1. In Visual Studio Solution Explorer select and hold (or right-click) the project name.

  2. In the drop-down menu, select Publish.

  3. In the displayed window, select the New link.

  4. In the dialog window, select App Service on the left and Create New on the right.

  5. Select the Publish button.

  6. In the next dialog window, enter the required information. The following is an example:

    auth-app-service

  7. Select Create.

  8. If the deployment completes successfully, you should see it reflected in Visual Studio. Moreover, a page is displayed in your default browser saying Your bot is ready!. The URL will be similar to this: https://botteamsauth.azurewebsites.net/. Save it to a file.

  9. In your browser, navigate to the Azure portal.

  10. Check your resource group, the bot should be listed along with the other resources. The following image is an example:

    teams-bot-auth-app-service-group

  11. In the resource group, select the bot channel registration name (link).

  12. In the left panel, select Settings.

  13. In the Messaging endpoint box, enter the URL obtained above followed by api/messages. This is an example: https://botteamsauth.azurewebsites.net/api/messages.

  14. Select the Save button in the upper left.

Test the bot using the Emulator

If you haven't done it already, install the Microsoft Bot Framework Emulator. See also Debug with the Emulator.

In order for the bot sample login to work you must configure the Emulator as shown below.

Configure the Emulator for authentication

If a bot requires authentication, you must configure the Emulator as shown below.

  1. Start the Emulator.
  2. In the Emulator, select the gear icon βš™ in the bottom left, or the Emulator Settings tab in the upper right.
  3. Check the box by Use version 1.0 authentication tokens.
  4. Enter the local path to the ngrok tool. See the Bot Framework Emulator / ngrok tunneling integration Wiki. For more tool information, see ngrok.
  5. Check the box by Run ngrok when the Emulator starts up.
  6. Select the Save button.

When the bot displays a sign-in card and the user selects the sign-in button, the Emulator opens a page that the user can use to sign in with the authentication provider. Once the user does so, the provider generates a user token and sends it to the bot. After that, the bot can act on behalf of the user.

Test the bot locally

After you have configured the authentication mechanism, you can perform the actual bot testing.

  1. Run the bot sample locally on your machine, via Visual Studio for example.

  2. Start the Emulator.

  3. Select the Open bot button.

  4. In the Bot URL, enter the bot's local URL. Usually, http://localhost:3978/api/messages.

  5. In the Microsoft App ID enter the bot's app ID from appsettings.json.

  6. In the Microsoft App password enter the bot's app password from the appsettings.json.

  7. Select Connect.

  8. After the bot is up and running, enter any text to display the sign-in card.

  9. Select the Sign in button.

  10. A pop-up dialog is displayed to Confirm Open URL. This is to allow the bot's user (you) to be authenticated.

  11. Select Confirm.

  12. If asked, select the applicable user's account.

  13. Depending which configuration you used for the Emulator, you get one of the following:

    1. Using sign-in verification code
      βœ“ A window is opened displaying the validation code.
      βœ“ Copy and enter the validation code into the chat box to complete the sign-in.
    2. Using authentication tokens.
      βœ“ You're logged in based on your credentials.

    The following image is an example of the bot UI after you've logged in:

    auth bot login emulator

  14. If you select Yes when the bot asks Would you like to view your token?, you'll get a response similar to the following:

    auth bot login emulator token

  15. Enter logout in the input chat box to sign out. This releases the user token, and the bot won't be able to act on your behalf until you sign in again.

Note

Bot authentication requires use of the Bot Connector Service. The service accesses the bot channels registration information for your bot.

Test the deployed bot

  1. In your browser, navigate to the Azure portal.

  2. Find your resource group.

  3. Select the resource link. The resource page is displayed.

  4. In the resource page, select Test in Web Chat. The bot starts and displays the predefined greetings.

  5. Type anything in the chat box.

  6. Select the Sign in box.

  7. A pop-up dialog is displayed to Confirm Open URL. This is to allow the bot's user (you) to be authenticated.

  8. Select Confirm.

  9. If asked, select the applicable user's account. The following image is an example of the bot UI after you have logged in:

    auth bot login deployed.

  10. Select the Yes button to display your authentication token. The following image is an example:

    auth bot login deployed token.

  11. Enter logout to sign out.

    auth bot deployed logout

Note

If you're having problems signing in, try to test the connection again as described in the previous steps. This could recreate the authentication token. With the Bot Framework Web Chat client in Azure, you may need to sign in several times before the authentication is established correctly.

Install and test the bot in Teams

  1. In your bot project, ensure that the TeamsAppManifest folder contains the manifest.json along with an outline.png and color.png files.

  2. In Solution Explorer, navigate to the TeamsAppManifest folder. Edit manifest.json by assigning the following values:

    1. Ensure that the bot App ID you received at the time of the bot channel registration is assigned to id and botId.
    2. Assign this value: validDomains: [ "token.botframework.com" ].
  3. Select and zip the manifest.json, outline.png, and color.png files.

  4. Open Microsoft Teams.

  5. In the left panel, at the bottom, select the Apps icon.

  6. In the right panel, at the bottom, select Upload a custom app.

  7. Navigate to the TeamsAppManifest folder and upload the zipped manifest. The following wizard is displayed:

    auth bot teams upload

  8. Select the Add to a team button.

  9. In the next window, select the team where you want to use the bot.

  10. Select the Set up a bot button.

  11. Select the three dots (●●●) in the left panel. Then select the App Studio icon.

  12. Select the Manifest editor tab. You should see the icon for the bot you uploaded.

  13. Also, you should be able to see the bot listed as a contact in the chat list that you can use to exchange messages with the bot.

Testing the bot locally in Teams

Microsoft Teams is an entirely cloud-based product, it requires all services it accesses to be available from the cloud using HTTPS endpoints. Therefore, to enable the bot (our sample) to work in Teams, you need to either publish the code to the cloud of your choice, or make a locally running instance externally accessible via a tunneling tool. We recommend ngrok, which creates an externally addressable URL for a port you open locally on your machine. To set up ngrok in preparation for running your Microsoft Teams app locally, follow these steps:

  1. In a terminal window, go the directory where you have ngrok.exe installed. We suggest setting the environment variable path to point to it.

  2. Run, for example, ngrok http 3978 --host-header=localhost:3978. Replace the port number as needed. This launches ngrok to listen on the port you specify. In return, it gives you an externally addressable URL, valid for as long as ngrok is running. The following image is an example:

    teams bots app auth connection string adv1.

  3. Copy the forwarding HTTPS address. It should be similar to the following: https://dea822bf.ngrok.io/.

  4. Append /api/messages to obtain https://dea822bf.ngrok.io/api/messages. This is the messages endpoint for the bot running locally on your machine and reachable over the web in a chat in Microsoft Teams.

  5. One final step to perform is to update the messages endpoint of the deployed bot. In the example, we deployed the bot in Azure. So **let's perform these steps:

    1. In your browser navigate to the Azure portal.
    2. Select your Bot Channel Registration.
    3. In the left panel, select Settings.
    4. In the right panel, in the Messaging endpoint box, enter the ngrok URL, in our example, https://dea822bf.ngrok.io/api/messages.
  6. Start your bot locally, for example in Visual Studio debug mode.

  7. Test the bot while running locally using the Bot Framework portal's Test Web chat. Like the Emulator, this test doesn't allow you to access Teams-specific functionality.

  8. In the terminal window where ngrok is running you can see HTTP traffic between the bot and the web chat client. If you want a more detailed view, in a browser window enter http://127.0.0.1:4040 you obtained from the previous terminal window. The following image is an example:

    auth bot teams ngrok testing.

Note

If you stop and restart ngrok, the URL changes. To use ngrok in your project, and depending on the capabilities you're using, you must update all URL references.

Additional information

TeamsAppManifest/manifest.json

This manifest contains information needed by Microsoft Teams to connect with the bot.

{
  "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.3/MicrosoftTeams.schema.json",
  "manifestVersion": "1.3",
  "version": "1.0.0",
  "id": "",
  "packageName": "com.teams.auth.bot",
  "developer": {
    "name": "TeamsBotAuth",
    "websiteUrl": "https://www.microsoft.com",
    "privacyUrl": "https://www.teams.com/privacy",
    "termsOfUseUrl": "https://www.teams.com/termsofuse"
  },
  "icons": {
    "color": "color.png",
    "outline": "outline.png"
  },
  "name": {
    "short": "TeamsBotAuth",
    "full": "Teams Bot Authentication"
  },
  "description": {
    "short": "TeamsBotAuth",
    "full": "Teams Bot Authentication"
  },
  "accentColor": "#FFFFFF",
  "bots": [
    {
      "botId": "",
      "scopes": [
        "groupchat",
        "team"
      ],
      "supportsFiles": false,
      "isNotificationOnly": false
    }
  ],
  "permissions": [
    "identity",
    "messageTeamMembers"
  ],
  "validDomains": [ "token.botframework.com" ]
}

With authentication Teams behaves slightly different than other channels, as explained below.

Handling Invoke Activity

An Invoke Activity is sent to the bot rather than the Event Activity used by other channels. This is done by sub-classing the ActivityHandler.

Bots\DialogBots.cs

public class DialogBot<T> : TeamsActivityHandler where T : Dialog
{
    protected readonly BotState ConversationState;
    protected readonly Dialog Dialog;
    protected readonly ILogger Logger;
    protected readonly BotState UserState;

    public DialogBot(ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger)
    {
        ConversationState = conversationState;
        UserState = userState;
        Dialog = dialog;
        Logger = logger;
    }

    public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        await base.OnTurnAsync(turnContext, cancellationToken);

        // Save any state changes that might have occured during the turn.
        await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
        await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
    }

    protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
    {
        Logger.LogInformation("Running dialog with Message Activity.");

        // Run the Dialog with the new message Activity.
        await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
    }
}

Bots\TeamsBot.cs

The Invoke Activity must be forwarded to the dialog if the OAuthPrompt is used.

protected override async Task OnSigninVerifyStateAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken)
{
    Logger.LogInformation("Running dialog with signin/verifystate from an Invoke Activity.");

    // OAuth Prompt needs to see the Invoke Activity in order to complete the login process.
    // Run the Dialog with the new Invoke Activity.
    await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
}

TeamsActivityHandler.cs


protected virtual Task OnInvokeActivityAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken)
{
    switch (turnContext.Activity.Name)
    {
        case "signin/verifyState":
            return OnSigninVerifyStateAsync(turnContext, cancellationToken);

        default:
            return Task.CompletedTask;
    }
}

protected virtual Task OnSigninVerifyStateAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken)
{
    return Task.CompletedTask;
}

Further reading