Updates from: 11/23/2022 02:51:56
Service Microsoft Docs article Related commit history on GitHub Change details
platform Add Authentication https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/authentication/add-authentication.md
Title: Add authentication to your Teams bot
-description: Learn how to enable authentication using third-party OAuth provider to a bot app in Teams using Azure AD.
+description: Learn how to enable authentication using third-party provider to a bot app in Teams using Azure AD.
ms.localizationpriority: medium
You use a resource group to create individual resources for the Bot Framework. F
The Azure Bot resource registration registers your web service as a bot with the Bot Framework, which provides you 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](/azure/bot-service/abs-quickstart?view=azure-bot-service-4.0&viewFallbackFrom=azure-bot-service-3.0&preserve-view=true) through the Azure portal then it is already registered with the service. If you created your bot through the [Bot Framework](https://dev.botframework.com/bots/new) or [Developer Portal](../../../concepts/build-and-test/teams-developer-portal.md) your bot isn't registered in Azure.
+> You only need to register your bot if it's not hosted in Azure. If you [created a bot](/azure/bot-service/abs-quickstart?view=azure-bot-service-4.0&viewFallbackFrom=azure-bot-service-3.0&preserve-view=true) through the Azure portal then it's already registered with the service. If you created your bot through the [Bot Framework](https://dev.botframework.com/bots/new) or [Developer Portal](../../../concepts/build-and-test/teams-developer-portal.md) your bot isn't registered in Azure.
1. Visit [**Azure portal**][azure-portal] and search for **Azure Bot** in **Create a resource** section. 1. Open the **Azure Bot** and select **Create**.
To create client secret:
1. Next to **Microsoft App ID**, select **Manage**.
- :::image type="content" source="~/assets/images/manage-bot-label.png" alt-text="This screenshot shows how to create manage bot.":::
+ :::image type="content" source="~/assets/images/manage-bot-label.png" alt-text="This screenshot shows how to create and manage a bot.":::
1. In the **Client secrets** section, select **New client secret**.**Add a client secret** window appears.
For more information, see [Create a bot for Teams](../create-a-bot-for-teams.md)
## 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.
+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**][azure-portal], on the left navigation panel, select **Azure Active Directory**. > [!TIP]
In this procedure, you'll use an Azure AD provider; other Azure AD supported ide
✓ Set the URL to `https://token.botframework.com/.auth/web/redirect`. 1. Select **Register**.
-1. Once it's created, Azure displays the **Overview** page for the app. Copy and save the following information to a file:
+1. After it's 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. 1. 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.
In this procedure, you'll use an Azure AD provider; other Azure AD supported ide
### Configure the identity provider connection and register it with the bot
-Note-there are two options for Service Providers here- Azure AD V1 and Azure AD V2. The differences between the two providers are summarized [here](/azure/active-directory/azuread-dev/azure-ad-endpoint-comparison), but in general, V2 provides more flexibility with respect to changing bot permissions. Graph API permissions are listed in the scopes field, and as new ones are added, bots will allow users to consent to the new permissions on the next sign in. For V1, the bot consent must be deleted by the user for new permissions to be prompted in the OAuth dialog.
+Note: There are two options for Service Providers here, Azure AD V1 and Azure AD V2. The differences between the two providers are summarized [here](/azure/active-directory/azuread-dev/azure-ad-endpoint-comparison), but in general, V2 provides more flexibility with respect to changing bot permissions. Graph API permissions are listed in the scopes field, and as new ones are added, bots will allow users to consent to the new permissions on the next sign in. For V1, the bot consent must be deleted by the user for new permissions to be prompted in the OAuth dialog.
#### Microsoft Azure Active Directory (Azure AD) V1
With the preliminary settings done, let's focus on the creation of the bot to us
# [C#/.NET](#tab/dotnet) 1. Clone [cs-auth-sample][teams-auth-bot-cs].
-1. Launch Visual Studio.
-1. From the toolbar, select **File -> Open -> Project/Solution** and open the bot project.
+1. Open Visual Studio.
+1. From the toolbar, select **File > Open > Project/Solution** and open the bot project.
1. In C#, Update **appsettings.json** as follows: - Set `ConnectionName` to the name of the identity provider connection you added to the bot registration. The name we used in this example is *BotTeamsAuthADv1*.
With the preliminary settings done, let's focus on the creation of the bot to us
# [Python](#tab/python)
-1. Clone [py-auth-sample][teams-auth-bot-py] from the github repository.
+1. Clone [py-auth-sample][teams-auth-bot-py] from the GitHub repository.
1. Update **config.py**: - Set `ConnectionName` to the name of the OAuth connection setting you added to your bot.
and when for these, and just reference that from here, along with the set of ste
1. Go to the `TeamsAppManifest` folder and upload the zipped manifest. The following wizard is displayed:
- :::image type="content" source="../../../assets/images/authentication/auth-bot-teams-upload.png" alt-text="This screenshot shows an example of the bot after it is uploaded into Teams.":::
+ :::image type="content" source="../../../assets/images/authentication/auth-bot-teams-upload.png" alt-text="This screenshot shows an example of the bot after it's uploaded into Teams.":::
1. Select the **Add to a team** button. 1. In the next window, select the team where you want to use the bot.
This section provides Bot authentication v3 SDK sample.
| **Sample name** | **Description** | **.NET** | **Node.js** | **Python** | ||||-|| | Bot authentication | This sample shows how to get started with authentication in a bot for Teams. | [View](https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/46.teams-auth) | [View](https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/javascript_nodejs/46.teams-auth) | [View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/python/46.teams-auth) |
-| Tab, Bot and Message Extension (ME) SSO | This sample shows SSO for Tab, Bot and ME - search, action, linkunfurl. | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-sso/csharp) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-sso/nodejs) | Not available |
+| Tab, Bot and Message Extension (ME) SSO | This sample shows SSO for Tab, Bot and ME - search, action, link unfurl. | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-sso/csharp) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-sso/nodejs) | Not available |
## See also
platform Auth Aad Sso Bots https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/authentication/auth-aad-sso-bots.md
- Title: Single sign-on support for bots
-description: Enable Single sign-on (SSO) using Azure AD configuration and OAuth card support for Teams bot apps.
---
-# Use SSO authentication for bots
-
-Single sign-on (SSO) authentication in Microsoft Azure Active Directory (Azure AD) silently refreshes the authentication token to minimize the number of times users need to enter their sign in credentials. If users agree to use your app, they don't have to provide consent again on another device as they're signed in automatically. Tabs and bots have similar flow for SSO support, but bot [requests tokens](#request-a-bot-token) and [receives responses](#receive-the-bot-token) with a different protocol.
-
->[!NOTE]
->
-> * OAuth 2.0 is an open standard for authentication and authorization used by Azure AD and many other identity providers. A basic understanding of OAuth 2.0 is a prerequisite for working with authentication in Teams.
->
-> * Bot SSO is supported only in one-on-one chat.
-
-See the following video to learn about SSO support for bots:
-<br>
-> [!VIDEO https://www.microsoft.com/en-us/videoplayer/embed/RE4OASc]
-<br>
-
-## Bot SSO at runtime
-
-The following image illustrates the flow of SSO in bots:
--
-The following steps help you with authentication and bot application tokens:
-
-1. The bot sends a message to Teams with an OAuthCard that contains `tokenExchangeResource` to obtain an authentication token for the bot application. The user receives messages at all the active user endpoints.
-
- > [!NOTE]
- >
- > * A user can have more than one active endpoint at a time.
- > * The bot token is received from every active user endpoint.
- > * The app must be installed in personal scope for SSO support.
-
-1. If the current user is using your bot application for the first time, a request prompt appears to the user to do one of the following actions:
- * Provide consent, if necessary.
- * Handle step-up authentication, such as two-factor authentication.
-
-1. Teams requests the bot application token from the Azure AD endpoint for the current user.
-
-1. Azure AD sends the bot application token to the Teams application.
-
-1. Teams sends the token to the bot as part of the value object returned by the invoking with **sign in** or **tokenExchange**.
-
-1. The parsed token in the bot application provides the required information, such as the user's email address.
-
-## Develop an SSO Teams bot
-
-The following steps guide you to develop SSO Teams bot:
-
-1. [Register your app through the Azure AD portal](#register-your-app-through-the-azure-ad-portal).
-1. [Update your Teams application manifest for your bot](#update-your-teams-application-manifest-for-your-bot).
-1. [Add the code to request and receive a bot token](#add-the-code-to-request-and-receive-a-bot-token).
-
-### Register your app through the Azure AD portal
-
-The steps to register your app through the Azure AD portal are similar to the [tab SSO flow](../../../tabs/how-to/authentication/tab-sso-overview.md). The following steps guide you to register your app:
-
-1. Register a new application in the [Azure Active Directory ΓÇô App Registrations](https://go.microsoft.com/fwlink/?linkid=2083908) portal.
-
-1. Select **New Registration**. The **Register an application** page appears.
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/app-registration.png" alt-text="Screenshot of the AAD app registrations. The menu entry titled New registration.":::
-
-1. In the **Register an application**, do the following steps:
-
- > [!NOTE]
- >
- > The users are not asked for consent and are granted access tokens right away, if the Azure AD app is registered in the same tenant where they are making an authentication request in Teams. However, the users must provide consent to the permissions, if the Azure AD app is registered in a different tenant.
-
- * Enter **Name** for your app.
- * Select **Supported account types**, such as single tenant or multitenant.
- * Select **Register**.
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/register-application.png" alt-text="Screenshot of the AAD app registrations. The menu entry titled register an application.":::
-
-1. Go to overview page.
-1. Copy the value of **Application (client) ID**.
-1. Under **Manage**, go to **Expose an API**.
-
- > [!TIP]
- > To update your app manifest later, save the **Application (client) ID** value.
-
- > [!IMPORTANT]
- >
- > * If you are building a standalone bot, enter the Application ID URI as `api://botid-{YourBotId}`. Here *YourBotId* is your Azure AD application ID.
- > * If you are building an app with a bot and a tab, enter the Application ID URI as `api://fully-qualified-domain-name.com/botid-{YourBotId}`.
-
-1. Select **Add a scope**.
-1. In the panel that prompts, enter `access_as_user` as the **Scope name**.
-
- >[!NOTE]
- > The "access_as_user" scope used to add a client app is for "Administrators and users".
- >
- > You must be aware of the following important restrictions:
- >
- > * Only user-level Microsoft Graph API permissions, such as email, profile, offline_access, and OpenId are supported. If you need access to other Microsoft Graph scopes, such as `User.Read` or `Mail.Read`, see [Extend tab app with Microsoft Graph permissions and scope](../../../tabs/how-to/authentication/tab-sso-graph-api.md).
- > * Your application's domain name must be same as the domain name that you have registered for your Azure AD application.
- > * Multiple domains per app are currently not supported.
- > * Applications that use the `azurewebsites.net` domain are not supported because it is common and may be a security risk.
-
-1. In the **Who can consent?**, enter **Admins and users**.
-1. Enter the following details to configure the admin and user consent prompts with values that are appropriate for the `access_as_user`scope.
- * **Admin consent display name**: Teams can access the userΓÇÖs profile.
- * **Admin consent description**: Teams can call the appΓÇÖs web APIs as the current user.
- * **User consent display name**: Teams can access your profile and make requests on your behalf.
- * **User consent description**: Teams can call this appΓÇÖs APIs with the same rights as you have.
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/add-a-scope.png" alt-text="Screenshot of the AAD app registrations. The menu entry titled add a scope.":::
-
-1. Ensure that the state is set to **Enabled**.
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/enabled-state.png" alt-text="Screenshot of the AAD app registrations scope. The menu entry titled State":::
-
-1. Select **Add scope** to save the details. The domain part of the **Scope name** displayed must automatically match the **Application ID** URI set in the previous step, with `/access_as_user` appended to the end `api://subdomain.example.com/00000000-0000-0000-0000-000000000000/access_as_user`.
-
-1. In the **Authorized client applications**, identify the applications that you want to authorize for your appΓÇÖs web application.
-1. Select **Add a client application**.
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/add-client-application.png" alt-text="Screenshot of the AAD app registrations. The menu entry titled add a client application.":::
-
-1. Enter each of the following client IDs and select the authorized scope you created in the previous step:
- * `1fec8e78-bce4-4aaf-ab1b-5451cc387264` for Teams mobile or desktop application.
- * `5e3ce6c0-2b1f-4285-8d4b-75ee78787346` for Teams web application.
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/add-client-id.png" alt-text="Screenshot of the AAD app registrations. The menu entry titled add application.":::
-
-1. Go to **Authentication**.
-1. In **Platform configurations**, select **Add a platform**.
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/platform-configuration.png" alt-text="Screenshot of the AAD app registrations platform configurations. The menu entry titled add a platform.":::
-
-1. Select **Web**.
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/configure-platform.png" alt-text="Screenshot of the AAD app registrations configure platforms. The menu entry titled web. ":::
-
-1. Enter the **Redirect URIs** for your app.
-
- >[!NOTE]
- > This URI should be a fully qualified domain name. It's also followed by the API route where an authentication response is sent. If you're following any of the Teams samples, the URI is `https://token.botframework.com/.auth/web/redirect`. For more information, see [OAuth 2.0 authorization code flow](/azure/active-directory/develop/v2-oauth2-auth-code-flow).
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/configure-web.png" alt-text="Screenshot of the AAD app registrations configure web. The menu entry titled redirect URIs.":::
-
-1. The following steps will help you to enable implicit grant:
- * Select **Authentication** from the left pane.
- * Select the **Access tokens** and **ID tokens** checkboxes.
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/grant-flow.png" alt-text="Screenshot of the AAD app registrations. The menu entry titled grant flows.":::
-
- * Select **Save** to save the changes.
-
-1. Add necessary **API Permissions**.
- * Select **API permissions** from the left pane.
- * Select **Add a platform** to add any permissions that your app requires to downstream APIs, for example, User.Read.
-
-#### Update manifest in Microsoft Azure portal
-
-The following steps will guide you to update the bot manifest in Azure portal:
-
-1. Select **Manifest** from the left pane.
-1. Ensure the config item is set to **"accessTokenAcceptedVersion": 2**. If not, change it's value to **2**.
-
- :::image type="content" source="~/assets/images/bots/update-manifest.png" alt-text="Screenshot of the application manifest after you have successfully completed the registration of the application in AAD.":::
-
- >[!NOTE]
- > If you are already in testing your bot in Teams, you must sign out from this app and sign out from Teams. Then sign in again to see this change.
-
-1. Select **Save**.
-
-#### Update the Azure portal with the OAuth connection
-
-The following steps will guide you to update the Azure portal with the OAuth connection:
-
-1. In the Azure portal, go to [**AzureBot**](https://ms.portal.azure.com/#create/Microsoft.AzureBot).
-1. Go to **Configuration** on the left pane.
-1. Select **Add OAuth Connection Settings**.
-
- :::image type="content" source="~/assets/images/authentication/SSO-bots-auth/auth-setting2.png" alt-text="Screenshot of the AAD app registrations. The menu entry titled Add OAuth Connection Settings.":::
-
-1. The following steps will guide you to complete the **New Connection Setting** form:
-
- >[!NOTE]
- > **Implicit grant** may be required in the Azure AD application.
-
- * Enter **Name** in the **New Connection Setting** page.
-
- >[!NOTE]
- > The **Name** is referred to the settings of your bot service code in *step 5* of [Bot SSO at runtime](#bot-sso-at-runtime).
-
- * From the **Service Provider** dropdown menu, select **Azure Active Directory v2**.
- * Enter the client credentials, such as **Client Id** and **Client secret** for the Azure AD application.
- * For the **Token Exchange URL**, use the scope value defined in [Update your Teams application manifest for your bot](#update-your-teams-application-manifest-for-your-bot), for example, `api://botid-<your-app-id>/`. The Token Exchange URL indicates to the SDK that this Azure AD application is configured for SSO.
- * In the **Tenant ID**, enter *common*.
- * Add all the **Scopes** configured when specifying permissions to downstream APIs for your Azure AD application. With the Client ID and Client secret provided, the token store exchanges the token for a graph token with defined permissions.
- * Select **Save**.
- * Select **Apply**.
-
- :::image type="content" source="~/assets/images/authentication/Bot-connection-setting.png" alt-text="Screenshot of the AAD app registrations. The menu entry titled New Connection Setting.":::
-
-### Update your Teams application manifest for your bot
-
-If the application contains a standalone bot, then use the following code to add new properties to the Teams application manifest:
-
-```json
- "webApplicationInfo":
- {
- "id": "00000000-0000-0000-0000-000000000000",
- "resource": "api://botid-00000000-0000-0000-0000-000000000000"
- }
-```
-
-If the application contains a bot and a tab, then use the following code to add new properties to the Teams application manifest:
-
-```json
- "webApplicationInfo":
- {
- "id": "00000000-0000-0000-0000-000000000000",
- "resource": "api://subdomain.example.com/botid-00000000-0000-0000-0000-000000000000"
- }
-```
-
-**webApplicationInfo** is the parent of the following elements:
-
-* **id** - The client ID of the application. It's the application ID that you obtained as part of registering the application with Azure AD. Don't share this Application ID with multiple Teams apps. Create a new Azure AD app for each application manifest that uses `webApplicationInfo`.
-* **resource** - The domain and subdomain of your application. It's the same URI, including the `api://` protocol that you registered when creating your `scope` in [Register your app through the Azure AD portal](#register-your-app-through-the-azure-ad-portal). Don't include the `access_as_user` path in your resource. The domain part of this URI must match the domain and subdomains used in the URLs of your Teams application manifest.
-
-### Add the code to request and receive a bot token
-
-#### Request a bot token
-
-The request to get the token is a normal POST message request using the existing message schema. It's included in the attachments of an OAuthCard. The schema for the OAuthCard class is defined in [Microsoft Bot Schema 4.0](/dotnet/api/microsoft.bot.schema.oauthcard?view=botbuilder-dotnet-stable&preserve-view=true) and it's similar to a sign in card. Teams treats this request as a silent token acquisition if the `TokenExchangeResource` property is populated on the card. For the Teams channel, only the `Id` property, which uniquely identifies a token request, is honored.
-
->[!NOTE]
-> The Microsoft Bot Framework `OAuthPrompt` or the `MultiProviderAuthDialog` is supported for SSO authentication.
-
-If the user is using the application for the first time and user consent is required, the following dialog appears to continue with the consent experience:
--
-When the user selects **Continue**, the following events occur:
-
-* If the bot defines a sign in button, the sign in flow for bots is activated that is similar to the sign in flow from an OAuth card button in a message stream. The developer must decide which permissions require user's consent. This approach is recommended if you require a token with permissions beyond `openId`. For example, if you want to exchange the token for graph resources.
-
-* If the bot isn't providing a sign in button on the OAuth card, user consent is required for a minimal set of permissions. This token is useful for basic authentication and to get the user's email address.
-
-##### C# token request without a sign in button
-
-```csharp
- var attachment = new Attachment
- {
- Content = new OAuthCard
- {
- TokenExchangeResource = new TokenExchangeResource
- {
- Id = requestId
- }
- },
- ContentType = OAuthCard.ContentType,
- };
- var activity = MessageFactory.Attachment(attachment);
-
- // NOTE: This activity needs to be sent in the 1:1 conversation between the bot and the user.
- // If the bot supports group and channel scope, this code should be updated to send the request to the 1:1 chat.
-
- await turnContext.SendActivityAsync(activity, cancellationToken);
-```
-
-#### Receive the bot token
-
-The response with the token is sent through an invoke activity with the same schema as other invoke activities that the bots receive today. The only difference is the invoke name, `signin` or `tokenExchange`, and the **value** field. The **value** field contains the **Id**, a string of the initial request to get the token and the **token** field, a string value including the token.
-
->[!NOTE]
->
-> * You might receive multiple responses for a given request if the user has multiple active endpoints. You must deduplicate the responses with the token.
-> * With latest SDK updates, token exchange and deduplication is handled by `TeamsSSOTokenExchangeMiddleware`. If the activity name is `signin` or `tokenExchange`, the middleware attempts to exchange the token and deduplicate the incoming call by ensuring that only one exchange request is processed. For more information, see [`TeamsSSOTokenExchangeMiddleware`](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/bot-conversation-sso-quickstart/csharp_dotnetcore/BotConversationSsoQuickstart/AdapterWithErrorHandler.cs#L26).
-
-```csharp
- protected override async Task OnTokenResponseEventAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
- {
- await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
- }
-```
-
-### Token exchange failure
-
-If there's a token exchange failure, use the following code:
-
-```json
-{ΓÇïΓÇï
- "status": "<response code>",
- "body":
- {ΓÇïΓÇï
- "id":"<unique Id>",
- "connectionName": "<connection Name on the bot (from the OAuth card)>",
- "failureDetail": "<failure reason if status code is not 200, null otherwise>"
- }ΓÇïΓÇï
-}ΓÇïΓÇï
-```
-
-To understand what the bot does when the token exchange fails to trigger a consent prompt, see the following steps:
-
->[!NOTE]
-> No user action is required to be taken as the bot takes the actions when the token exchange fails.
-
-1. The client starts a conversation with the bot triggering an OAuth scenario.
-2. The bot sends back an OAuth card to the client.
-3. The client intercepts the OAuth card before displaying it to the user and checks if it contains a `TokenExchangeResource` property.
-4. If the property exists, the client sends a `TokenExchangeInvokeRequest` to the bot. The client must have an exchangeable token for the user, which must be an Azure AD v2 token and whose audience must be the same as `TokenExchangeResource.Uri` property. The client sends an invoke activity to the bot with the following code:
-
- ```json
- {
- "type": "Invoke",
- "name": "signin/tokenExchange",
- "value":
- {
- "id": "<any unique Id>",
- "connectionName": "<connection Name on the skill bot (from the OAuth card)>",
- "token": "<exchangeable token>"
- }
- }
- ```
-
-5. The bot processes the `TokenExchangeInvokeRequest` and returns a `TokenExchangeInvokeResponse` back to the client. The client must wait until it receives the `TokenExchangeInvokeResponse`.
-
- ```json
- {
- "status": "<response code>",
- "body":
- {
- "id":"<unique Id>",
- "connectionName": "<connection Name on the skill bot (from the OAuth card)>",
- "failureDetail": "<failure reason if status code is not 200, null otherwise>"
- }
- }
- ```
-
-6. If the `TokenExchangeInvokeResponse` has a `status` of `200`, then the client doesn't show the OAuth card. See the [normal flow image](/azure/bot-service/bot-builder-concept-sso?view=azure-bot-service-4.0#sso-components-interaction&preserve-view=true). For any other `status` or if the `TokenExchangeInvokeResponse` isn't received, then the client shows the OAuth card to the user. See the [fallback flow image](/azure/bot-service/bot-builder-concept-sso?view=azure-bot-service-4.0#sso-components-interaction&preserve-view=true). If there are any errors or unmet dependencies like user consent, this activity ensures that the SSO flow falls back to normal OAuthCard flow.
-
-### Update the auth sample
-
-Open [Teams auth sample](https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/46.teams-auth), and then complete the following steps to update it:
-
-1. Update the TeamsBot to handle the deduping of the incoming request by including the following code:
-
- ```csharp
- protected override async Task OnSignInInvokeAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken)
- {
- await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
- }
- protected override async Task OnTokenResponseEventAsync(ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
- {
- await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
- }
- ```
-
-2. Update `appsettings.json` to include the `botId`, password, and the connection name defined in [Update the Azure portal with the OAuth connection](#update-the-azure-portal-with-the-oauth-connection).
-3. Update the manifest and ensure that `token.botframework.com` is in the valid domains list. For more information, see [Teams auth sample](https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/46.teams-auth).
-4. Zip the manifest with the profile images and install it in Teams.
-
-## Code sample
-
-|**Sample name** | **Description** |**.NET** |**C#** |**Node.js** |
-|-|--|--|--|--|
-|Bot framework SDK | This sample code demonstrates how to get started with authentication in a bot for Microsoft Teams. |[View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/46.teams-auth)|[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-conversation-sso-quickstart/csharp_dotnetcore/BotConversationSsoQuickstart)|[View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-conversation-sso-quickstart/js)|
-
-## Step-by-step guide
-
-Follow the [step-by-step guide](../../../sbs-bots-with-sso.yml), to build a bot with SSO authentication.
platform Auth Flow Bot https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/authentication/auth-flow-bot.md
- Title: Microsoft Teams Authentication flow for bots
-description: Enable authentication for Microsoft Teams bot app with third-party OAuth provider using code samples.
---
-# Authentication flow for bots in Microsoft Teams
-
-OAuth 2.0 is an open standard for authentication and authorization used by Azure Active Directory and many other identity providers. A basic understanding of OAuth 2.0 is a prerequisite for working with authentication in Teams; [here's a good overview](https://aaronparecki.com/oauth-2-simplified/) that's easier to follow than the [formal specification](https://oauth.net/2/). Authentication flow for tabs and bots is a little different ΓÇö tabs are similar to websites so they can use OAuth 2.0 directly, while bots aren't and must do a few things differently, but the core concepts are identical.
-
-See the GitHub repo [Microsoft Teams Authentication Sample](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-auth/nodejs)
-for an example that demonstrates authentication flow for bots using Node.js and the [OAuth 2.0 authorization code grant type](https://oauth.net/2/grant-types/authorization-code/).
-
-![Bot authentication sequence diagram](../../../assets/images/authentication/bot_auth_sequence_diagram.png)
-
-1. The user sends a message to the bot.
-2. The bot determines if the user needs to sign in.
- In this example, the bot stores the access token in its user data store. It asks the user to sign in if it doesn't have a validated token for the selected identity provider. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/src/utils/AuthenticationUtils.ts#L58-L76))
-3. The bot constructs the URL to the start page of the authentication flow, and sends a card to the user with a `signin` action. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/src/dialogs/BaseIdentityDialog.ts#L160-L190))</br>
- Like other application auth flows in Teams, the start page must be in a domain that's on your `validDomains` list, and in the same domain as the post-login redirect page.
- > [!IMPORTANT]
- > The OAuth 2.0 authorization code grant flow calls for a `state` parameter in the authentication request, which contains a unique session token to prevent a [cross-site request forgery attack](https://en.wikipedia.org/wiki/Cross-site_request_forgery). The example uses a randomly-generated GUID.
-4. When the user selects the *signin* button, Teams opens a pop-up window and navigates to the start page.
- > [!NOTE]
- > The size of the pop-up window can be controlled through width and height query string parameters in the URL. For example, if you add width=600 and height=600, the size of the pop-up window is 600x600 pixels. The actual size of the pop-up window is capped as a percentage of the Teams main window size. If the Teams window is small, the pop-up window is smaller than the specified dimensions.
-
-5. The start page redirects the user to the identity provider's `authorize` endpoint. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/public/html/auth-start.html#L51-L56))
-6. On the provider's site, the user signs in and grants access to the bot.
-7. The provider takes the user to the bot's OAuth redirect page with an authorization code.
-8. The bot redeems the authorization code for an access token, and **provisionally** associates the token with the user that initiated the sign-in flow. Below, we call this a *provisional token*.
- * In the example, the bot associates the value of the `state` parameter with the ID of the user that initiated the sign-in process so it can later match it with the `state` value returned by the identity provider. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/src/AuthBot.ts#L70-L99))
- > [!IMPORTANT]
- > The bot stores the token it receives from the identity provider and associates it with a specific user, but it is marked as "pending validation".
- * The provisional token can't be used without further validation.
- 1. **Validate what's received from the identity provider.** The value of the `state` parameter must be confirmed against what was saved earlier.
- 1. **Validate what's received from Teams.** A [two-step authentication](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) validation is performed to ensure that the user who authorized the bot with the identity provider is the same user who is chatting with the bot. This guards against [man-in-the-middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) and [phishing](https://en.wikipedia.org/wiki/Phishing) attacks. The bot generates a verification code and stores it, associated with the user. The verification code is sent automatically by Teams as described below. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/src/AuthBot.ts#L100-L113))
-9. The OAuth callback renders a page that calls `notifySuccess("<verification code>")`. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/master/src/views/oauth-callback-success.hbs))
-10. Teams closes the pop-up window and sends the `<verification code>` sent to `notifySuccess()` back to the bot. The bot receives an [invoke](/bot-framework/dotnet/bot-builder-dotnet-activities#invoke) message with `name = signin/verifyState`.
-11. The bot checks the incoming verification code against the verification code stored with the user's provisional token. ([View code](https://github.com/OfficeDev/microsoft-teams-sample-auth-node/blob/469952a26d618dbf884a3be53c7d921cc580b1e2/src/dialogs/BaseIdentityDialog.ts#L127-L140))
-12. If they match, the bot marks the token as validated and ready for use. Otherwise, the auth flow fails, and the bot deletes the provisional token.
-
- > [!NOTE]
- > If you experience issues with authentication on mobile, ensure your JavaScript SDK is updated to version 1.4.1 or later.
-
-## Code sample
-
-Sample code showing the bot authentication process:
-
-| **Sample name** | **Description** | **Node.js** | **.NET** | **Python** |
-|--|-|--|-|--|
-| Teams authentication | This sample demonstrates authentication in Microsoft Teams apps. | [View](https://github.com/OfficeDev/microsoft-teams-sample-auth-node) | | |
-| Bot authentication | This sample demonstrates how to use authentication for a bot running in Microsoft Teams | [View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/javascript_nodejs/46.teams-auth) | [View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/46.teams-auth) | [View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/python/46.teams-auth)
-
-## See also
-
-[Add authentication to your Teams bot](add-authentication.md)
platform Bot Sso Code https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/authentication/bot-sso-code.md
+
+ Title: Code configuration for enabling SSO for bots
+description: Describes code configuration for enabling SSO for bots.
+
+ms.localizationpriority: high
+zone_pivot_groups: enable-sso
+
+# Add code to enable SSO in your bot app
+
+Before you add code to enable SSO, ensure that you've configured your app and bot resource in Azure AD portal.
+
+> [!div class="nextstepaction"]
+> [Configure bot app in Azure AD](bot-sso-register-aad.md)
+
+You need to configure your app's code to obtain an access token from Azure AD. The access token is issued on behalf of the bot app.
+
+> [!NOTE]
+> If you've built your Teams app using Microsoft Teams Toolkit, you can enable SSO for your app using the instructions in the Tools and SDKs module. For more information, see [Add single sign-on to Teams app](../../../toolkit/add-single-sign-on.md). Teams Toolkit supports SSO for JavaScript and TypeScript apps in Visual Studio Code, and in Teams Toolkit 17.4 preview 3 for C# apps.
++
+This section covers:
+
+1. [Update development environment variables](#update-development-environment-variables)
+1. [Add code to handle an access token](#add-code-to-handle-an-access-token)
+1. [Add code to receive the token](#add-code-to-receive-the-token)
+1. [Handle app user log out](#handle-app-user-log-out)
+
+## Update development environment variables
+
+You've configured client secret and OAuth connection setting for the app in Azure AD. You must configure the code with these values.
+
+To update the development environment variables:
+
+1. Open the bot app project.
+1. Open the environment file for your project.
+1. Update the following variables:
+
+ - For `MicrosoftAppId`, update the bot ID from Azure AD.
+ - For `MicrosoftAppPassword`, update the client secret.
+ - For `ConnectionName`, update the name of the OAuth connection you configured in Azure AD.
+ - For `MicrosoftAppTenantId`, update the tenant ID.
+
+1. Save the file.
+
+You've now configured the required environment variables for your bot app and SSO. Next, add the code for handling bot tokens.
+
+## Add code to handle an access token
+
+The request to get the token is a POST message request using the existing message schema. It's included in the attachments of an OAuthCard. The schema for the OAuthCard class is defined in [Microsoft Bot Schema 4.0](/dotnet/api/microsoft.bot.schema.oauthcard?view=botbuilder-dotnet-stable&preserve-view=true). Teams refreshes the token if the `TokenExchangeResource` property is populated on the card. For the Teams channel, only the `Id` property, which uniquely identifies a token request, is honored.
+
+>[!NOTE]
+> The Microsoft Bot Framework `OAuthPrompt` or the `MultiProviderAuthDialog` is supported for SSO authentication.
+
+To update your app's code:
+
+1. Add code snippet for `TeamsSSOTokenExchangeMiddleware`.
+
+ # [csharp](#tab/cs1)
+
+ Add the following code snippet to `AdapterWithErrorHandler.cs` (or the equivalent class in your app's code):
+
+ ```csharp
+ base.Use(new TeamsSSOTokenExchangeMiddleware(storage, configuration["ConnectionName"]));
+ ```
+
+ # [JavaScript](#tab/js1)
+
+ Add the following code snippet to `index.js` (or the equivalent class in your app's code):
+
+ ```JavaScript
+ const {TeamsSSOTokenExchangeMiddleware} = require('botbuilder');
+ const tokenExchangeMiddleware = new TeamsSSOTokenExchangeMiddleware(memoryStorage, env.connectionName);
+ adapter.use(tokenExchangeMiddleware);
+ ```
+
+
+
+ >[!NOTE]
+ > You might receive multiple responses for a given request if the user has multiple active endpoints. You must eliminate all duplicate or redundant responses with the token. For more information about signin/tokenExchange, see [TeamsSSOTokenExchangeMiddleware Class](/python/api/botbuilder-core/botbuilder.core.teams.teams_sso_token_exchange_middleware.teamsssotokenexchangemiddleware?view=botbuilder-py-latest#remarks&preserve-view=true).
+
+1. Use the following code snippet for requesting a token.
+
+ # [csharp](#tab/cs2)
+
+ After you add the `AdapterWithErrorHandler.cs`, your code should be as shown below:
+
+ ```csharp
+ public class AdapterWithErrorHandler : CloudAdapter
+ {
+ public AdapterWithErrorHandler(
+ IConfiguration configuration,
+ IHttpClientFactory httpClientFactory,
+ ILogger<IBotFrameworkHttpAdapter> logger,
+ IStorage storage,
+ ConversationState conversationState)
+ : base(configuration, httpClientFactory, logger)
+ {
+ base.Use(new TeamsSSOTokenExchangeMiddleware(storage, configuration["ConnectionName"]));
+
+ OnTurnError = async (turnContext, exception) =>
+ {
+ // Log any leaked exception from the application.
+ // NOTE: In production environment, you should consider logging this to
+ // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how
+ // to add telemetry capture to your bot.
+ logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
+
+ // Send a message to the user.
+ await turnContext.SendActivityAsync("The bot encountered an error or bug.");
+ await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
+
+ if (conversationState != null)
+ {
+ try
+ {
+ // Delete the conversationState for the current conversation to prevent the
+ // bot from getting stuck in a error-loop caused by being in a bad state.
+ // conversationState should be thought of as similar to "cookie-state" in a Web pages.
+ await conversationState.DeleteAsync(turnContext);
+ }
+ catch (Exception e)
+ {
+ logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
+ }
+ }
+
+ // Send a trace activity, which will be displayed in the Bot Framework Emulator.
+ await turnContext.TraceActivityAsync(
+ "OnTurnError Trace",
+ exception.Message,
+ "https://www.botframework.com/schemas/error",
+ "TurnError");
+ };
+ }
+ }
+ ```
+
+ # [JavaScript](#tab/js2)
+
+ After you add the code snippet for `TeamsSSOTokenExchangeMiddleware`, your code should be as shown below:
+
+ ```JavaScript
+ // index.js is used to setup and configure your bot.
+
+ // Import required packages
+ const path = require('path');
+
+ // Read botFilePath and botFileSecret from .env file.
+ const ENV_FILE = path.join(__dirname, '.env');
+ require('dotenv').config({ path: ENV_FILE });
+
+ const restify = require('restify');
+
+ // Import required bot services.
+ // See https://aka.ms/bot-services to learn more about the different parts of a bot.
+ const {
+ CloudAdapter,
+ ConversationState,
+ MemoryStorage,
+ UserState,
+ ConfigurationBotFrameworkAuthentication,
+ TeamsSSOTokenExchangeMiddleware
+ } = require('botbuilder');
+
+ const { TeamsBot } = require('./bots/teamsBot');
+ const { MainDialog } = require('./dialogs/mainDialog');
+ const { env } = require('process');
+
+ const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(process.env);
+
+ var conname = env.connectionName;
+
+ console.log(`\n${ conname } is the con name`);
+
+ // Create adapter.
+ // See https://aka.ms/about-bot-adapter to learn more about how bots work.
+ const adapter = new CloudAdapter(botFrameworkAuthentication);
+ const memoryStorage = new MemoryStorage();
+ const tokenExchangeMiddleware = new TeamsSSOTokenExchangeMiddleware(memoryStorage, env.connectionName);
+
+ adapter.use(tokenExchangeMiddleware);
+ adapter.onTurnError = async (context, error) => {
+ // This check writes out errors to console log .vs. app insights.
+ // NOTE: In production environment, you should consider logging this to Azure
+ // application insights. See https://aka.ms/bottelemetry for telemetry
+ // configuration instructions.
+ console.error(`\n [onTurnError] unhandled error: ${ error }`);
+
+ // Send a trace activity, which will be displayed in Bot Framework Emulator.
+ await context.sendTraceActivity(
+ 'OnTurnError Trace',
+ `${ error }`,
+ 'https://www.botframework.com/schemas/error',
+ 'TurnError'
+ );
+
+ // Send a message to the user.
+ await context.sendActivity('The bot encountered an error or bug.');
+ await context.sendActivity('To continue to run this bot, please fix the bot source code.');
+ // Clear out state.
+ await conversationState.delete(context);
+ };
+
+ // Define the state store for your bot.
+ // See https://aka.ms/about-bot-state to learn more about using MemoryStorage.
+ // A bot requires a state storage system to persist the dialog and user state between messages.
+ //const memoryStorage = new MemoryStorage();
+
+ // Create conversation and user state with in-memory storage provider.
+ const conversationState = new ConversationState(memoryStorage);
+ const userState = new UserState(memoryStorage);
+
+ // Create the main dialog.
+ const dialog = new MainDialog();
+ // Create the bot that will handle incoming messages.
+ const bot = new TeamsBot(conversationState, userState, dialog);
+
+ // Create HTTP server.
+ const server = restify.createServer();
+ server.use(restify.plugins.bodyParser());
+
+ server.listen(process.env.port || process.env.PORT || 3978, function() {
+ console.log(`\n${ server.name } listening to ${ server.url }`);
+ console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
+ console.log('\nTo talk to your bot, open the emulator select "Open Bot"');
+ });
+
+ // Listen for incoming requests.
+ server.post('/api/messages', async (req, res) => {
+ // Route received a request to adapter for processing.
+ await adapter.process(req, res, (context) => bot.run(context));
+ });
+ ```
+
+
+
+### Consent dialog for getting access token
+
+If the app user is using the application for the first time and user consent is required, the following dialog box appears:
++
+When the user selects **Continue**, one of the following events occurs:
+
+- If the bot UI has a sign-in button, the sign-in flow for bots is activated. You can determine the permissions that require app user's consent. Use this approach if your app requires Graph permissions other than `openid`.
+
+- If the bot doesn't have a sign-in button on the OAuth card, app user consent is required for a minimal set of permissions. This token is useful for basic authentication and to get the app user's email address.
+
+The consent dialog that appears is for open-id scopes defined in Azure AD. The app user must give consent only once. After consenting, the app user can access and use your bot app for the granted permissions and scopes.
+
+> [!NOTE]
+> After the app user consents, they're not required to consent again for any other permissions. If the permissions defined in Azure AD scope are modified, then the app user may need to consent again. If, however, the consent prompt fails to let the app user access, the bot app falls back to sign-in card.
+
+> [!IMPORTANT]
+> Scenarios where consent dialogs are not needed:
+>
+> - If the tenant administrator has granted consent on behalf of the tenant, app users don't need to be prompted for consent at all. This means that the app users don't see the consent dialogs and can access the app seamlessly.
+> - If your Azure AD app is registered in the same tenant from which you're requesting an authentication in Teams, the app user can't be asked to consent, and is granted an access token right away. App users consent to these permissions only if the Azure AD app is registered in a different tenant.
+
+If you encounter any errors, see [Troubleshoot SSO authentication in Teams](../../../tabs/how-to/authentication/tab-sso-troubleshooting.md).
+
+## Add code to receive the token
+
+The response with the token is sent through an invoke activity with the same schema as other invoke activities that the bots receive today. The only difference is the invoke name, sign in/tokenExchange, and the **value** field. The **value** field contains the **Id**, a string of the initial request to get the token and the **token** field, a string value including the token.
+
+Use the following code snippet to invoke response:
+
+# [csharp](#tab/cs3)
+
+```csharp
+public MainDialog(IConfiguration configuration, ILogger<MainDialog> logger)
+ : base(nameof(MainDialog), configuration["ConnectionName"])
+ {
+ AddDialog(new OAuthPrompt(
+ nameof(OAuthPrompt),
+ new OAuthPromptSettings
+ {
+ ConnectionName = ConnectionName,
+ Text = "Please Sign In",
+ Title = "Sign In",
+ Timeout = 300000, // User has 5 minutes to login (1000 * 60 * 5)
+ EndOnInvalidMessage = true
+ }));
+
+ AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
+
+ AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
+ {
+ PromptStepAsync,
+ LoginStepAsync,
+ }));
+
+ // The initial child Dialog to run.
+ InitialDialogId = nameof(WaterfallDialog);
+ }
++
+private async Task<DialogTurnResult> PromptStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
+ {
+ return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken);
+ }
+
+private async Task<DialogTurnResult> LoginStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
+ {
+
+ var tokenResponse = (TokenResponse)stepContext.Result;
+ if (tokenResponse?.Token != null)
+ {
+ var token = tokenResponse.Token;
+
+ // On successful login, the token contains sign in token.
+ }
+ else
+ {
+ await stepContext.Context.SendActivityAsync(MessageFactory.Text("Login was not successful please try again."), cancellationToken);
+ }
+
+ return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
+ }
+```
+
+# [JavaScript](#tab/js3)
+
+```JavaScript
+class MainDailog {
+
+ this.addDialog(new OAuthPrompt(OAUTH_PROMPT, {
+ connectionName: process.env.connectionName,
+ text: 'Please Sign In',
+ Title: 'Sign In',
+ timeout: 300000
+ }));
+
+ this.addDialog(new ConfirmPrompt(CONFIRM_PROMPT));
+
+ this.addDialog(new WaterfallDialog(MAIN_WATERFALL_DIALOG, [
+ this.promptStep.bind(this),
+ this.loginStep.bind(this),
+ ]));
+
+ this.initialDialogId = MAIN_WATERFALL_DIALOG;
+
+ }
+
+async promptStep(stepContext) {
+ try {
+ return await stepContext.beginDialog(OAUTH_PROMPT);
+ } catch (err) {
+ console.error(err);
+ }
+ }
+
+async loginStep(stepContext) {
+ // Get the token from the previous step. Note that we could also have gotten the
+ // token directly from the prompt itself. There is an example of this in the next method.
+ const tokenResponse = stepContext.result;
+ if (!tokenResponse || !tokenResponse.token) {
+ await stepContext.context.sendActivity('Login was not successful please try again.');
+ } else {
+ const token = tokenResponse.token;
+ // On successful login, the token contains sign in token.
+ }
+ return await stepContext.endDialog();
+ }
+```
++
+> [!NOTE]
+> The code snippets use the Waterfall Dialog. For more information, see [About component and waterfall dialogs](/azure/bot-service/bot-builder-concept-waterfall-dialogs?view=azure-bot-service-4.0&preserve-view=true).
+
+### Validate the access token
+
+Web APIs on your server must decode the access token and verify if it's sent from the client.
+
+> [!NOTE]
+> If you use Bot Framework, it handles the access token validation. If you don't use Bot Framework, follow the guidelines given in this section.
+
+For more information about validating access token, see [Validate tokens](/azure/active-directory/develop/access-tokens#validate-tokens).
+
+There are a number of libraries available that can handle JWT validation. Basic validation includes:
+
+- Checking that the token is well-formed.
+- Checking that the token was issued by the intended authority.
+- Checking that the token is targeted to the web API.
+
+Keep in mind the following guidelines when validating the token:
+
+- Valid SSO tokens are issued by Azure AD. The `iss` claim in the token should start with this value.
+- The token's `aud1` parameter will be set to the app ID generated during Azure AD app registration.
+- The token's `scp` parameter will be set to `access_as_user`.
+
+#### Example access token
+
+The following is a typical decoded payload of an access token.
+
+```javascript
+{
+ aud: "2c3caa80-93f9-425e-8b85-0745f50c0d24",
+ iss: "https://login.microsoftonline.com/fec4f964-8bc9-4fac-b972-1c1da35adbcd/v2.0",
+ iat: 1521143967,
+ nbf: 1521143967,
+ exp: 1521147867,
+ aio: "ATQAy/8GAAAA0agfnU4DTJUlEqGLisMtBk5q6z+6DB+sgiRjB/Ni73q83y0B86yBHU/WFJnlMQJ8",
+ azp: "e4590ed6-62b3-5102-beff-bad2292ab01c",
+ azpacr: "0",
+ e_exp: 262800,
+ name: "Mila Nikolova",
+ oid: "6467882c-fdfd-4354-a1ed-4e13f064be25",
+ preferred_username: "milan@contoso.com",
+ scp: "access_as_user",
+ sub: "XkjgWjdmaZ-_xDmhgN1BMP2vL2YOfeVxfPT_o8GRWaw",
+ tid: "fec4f964-8bc9-4fac-b972-1c1da35adbcd",
+ uti: "MICAQyhrH02ov54bCtIDAA",
+ ver: "2.0"
+}
+```
+
+## Handle app user log out
+
+Use the following code snippet to handle the access token in case the app user logs out:
+
+# [csharp](#tab/cs4)
+
+```csharp
+ private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc,
+ CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (innerDc.Context.Activity.Type == ActivityTypes.Message)
+ {
+ var text = innerDc.Context.Activity.Text.ToLowerInvariant();
+
+ // Allow logout anywhere in the command.
+ if (text.IndexOf("logout") >= 0)
+ {
+ // The UserTokenClient encapsulates the authentication processes.
+ var userTokenClient = innerDc.Context.TurnState.Get<UserTokenClient>();
+ await userTokenClient.SignOutUserAsync(
+ innerDc.Context.Activity.From.Id,
+ ConnectionName,
+ innerDc.Context.Activity.ChannelId,
+ cancellationToken
+ ).ConfigureAwait(false);
+
+ await innerDc.Context.SendActivityAsync(MessageFactory.Text("You have been signed out."), cancellationToken);
+ return await innerDc.CancelAllDialogsAsync(cancellationToken);
+ }
+ }
+
+ return null;
+ }
+```
+
+# [JavaScript](#tab/js4)
+
+```JavaScript
+ async interrupt(innerDc) {
+ if (innerDc.context.activity.type === ActivityTypes.Message) {
+ const text = innerDc.context.activity.text.toLowerCase();
+ if (text === 'logout') {
+ const userTokenClient = innerDc.context.turnState.get(innerDc.context.adapter.UserTokenClientKey);
+
+ const { activity } = innerDc.context;
+ await userTokenClient.signOutUser(activity.from.id, this.connectionName, activity.channelId);
+
+ await innerDc.context.sendActivity('You have been signed out.');
+ return await innerDc.cancelAllDialogs();
+ }
+ }
+ }
+```
+++
+## Code sample
+
+| **Sample name** | **Description** | **C#** | **JavaScript** | **Node.js** |
+| | | | | |
+| Bot framework SDK | This sample code demonstrates how to get started with authentication in a bot for Microsoft Teams. | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-conversation-sso-quickstart/csharp_dotnetcore/BotConversationSsoQuickstart) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-conversation-sso-quickstart/js) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-conversation-sso-quickstart/js) |
+++++
+## Next step
+
+> [!div class="nextstepaction"]
+> [Update manifest for SSO and preview app](bot-sso-manifest.md)
platform Bot Sso Graph Api https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/authentication/bot-sso-graph-api.md
+
+ Title: Extend your app with Microsoft Graph permissions
+description: Describes configuring API permissions with Microsoft Graph for bot and messaging extensipn apps.
+
+ms.localizationpriority: high
+
+# Extend your app with Microsoft Graph permissions and scopes
+
+You can extend your bot and message extension apps by using Microsoft Graph. These permissions can allow app users to view user profile, to read mail, and more. Your app must ask for specific permission scopes to obtain the access tokens on app user's consent.
+
+Graph scopes, such as `User.Read` or `Mail.Read`, lets you specify how your app accesses a Teams user's account. You need to specify your scopes in the authorization request.
+
+In this section, you'll learn to [Configure API permissions in Azure AD](#configure-api-permissions-in-azure-ad).
+
+## Configure API permissions in Azure AD
+
+You can configure Graph scopes in Azure AD as required for your app. Delegated permissions are used by apps that require signed-in access. An app user or administrator who is signed-in must consent to them. Your app can consent on behalf of the signed-in user when it calls Microsoft Graph.
+
+### To configure API permissions
+
+1. Open the app you registered in the [Azure portal](https://ms.portal.azure.com/).
+
+2. Select **Manage** > **API permissions** from the left pane.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/api-permission-menu.png" alt-text="App permissions menu option." border="true":::
+
+ The **API permissions** page appears.
+
+3. Select **+ Add a permission** to add Microsoft Graph API permissions.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/app-permission.png" alt-text="App permissions page." border="true":::
+
+ The **Request API permissions** page appears.
+
+4. Select **Microsoft Graph**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/request-api-permission.png" alt-text="Request API permissions page." border="true":::
+
+ The options for Graph permissions display.
+
+5. Select **Delegated permissions** to view the list of permissions.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/delegated-permission.png" alt-text="Delegated permissions." border="true":::
+
+6. Select relevant permissions for your app, and then select **Add permissions**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/select-permission.png" alt-text="Select permissions." border="true":::
+
+ You can also enter the permission name in the search box to find it.
+
+ A message appears on the browser stating that the permissions were updated.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/updated-permission-msg.png" alt-text="Permissions updated message." border="true":::
+
+ The added permissions are displayed in the **API permissions** page.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/configured-permissions.png" alt-text="API permissions are configured." border="true":::
+
+ You've configured your app with Microsoft Graph permissions.
+
+After you've completed the configuration in Azure AD, you must update the code to acquire access token for Microsoft Graph. For more information, see [Bot framework SDK](https://github.com/microsoft/BotBuilder-Samples/blob/main/samples/csharp_dotnetcore/46.teams-auth/SimpleGraphClient.cs).
+
+The app user is prompted to consent for Graph permissions on the first time they use it. After the app user gives consent, the Graph permissions are granted.
platform Bot Sso Manifest https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/authentication/bot-sso-manifest.md
+
+ Title: Update manifest for enabling SSO for bot and messaging extension
+description: Describes updating manifest to enable SSO for bot and message extension.
+
+ms.localizationpriority: high
+
+# Update app manifest for SSO and preview your app
+
+Before you update Teams app manifest, ensure that you've configured code to enable SSO in your app.
+
+> [!div class="nextstepaction"]
+> [Add code](bot-sso-code.md)
+
+You've registered your app and bot resource in Azure AD. You've also configured code to handle tokens. Now, you must update the Teams app manifest to enable SSO for your app. The Teams app manifest describes how an app integrates into Teams.
+
+## webApplicationInfo property
+
+Configure the `webApplicationInfo` property in the Teams app manifest file. This property enables SSO for your app to help app users access your bot app seamlessly.
+
+`webApplicationInfo` has two elements, `id` and `resource`.
+
+| Element | Description |
+| | |
+| `id` | Enter the app ID (GUID) that you created in Azure AD. |
+| `resource` | Enter your app's subdomain URI and the application ID URI that you created in Azure AD when creating scope. You can copy it from the **Azure AD** > **Expose an API** section. |
+
+> [!NOTE]
+> Use manifest version 1.5 or higher to implement the `webApplicationInfo` property.
+
+The application ID URI that you registered in Azure AD is configured with the scope of the API you exposed. Configure your app's subdomain URI in `resource` to ensure that the authentication request using `getAuthToken()` is from the domain given in Teams app manifest.
+
+For more information, see [webApplicationInfo](../../../resources/schem#webapplicationinfo).
+
+## To configure Teams app manifest
+
+1. Open the app project.
+2. Open the manifest folder.
+
+ > [!NOTE]
+ >
+ > - The manifest folder should be at the root of your project. For more information, see [Create a Microsoft Teams app package](../../../concepts/build-and-test/apps-package.md).
+ > - For more information on learning how to create a manifest.json, see [Reference: Manifest schema for Microsoft Teams](../../../resources/schem).
+
+1. Open the `manifest.json` file.
+1. Add one of the following code snippets to the manifest file to add the new property.
+
+ - If your app has a standalone bot, add the following code snippet:
+
+ ```json
+ "webApplicationInfo":
+ {
+ "id": "00000000-0000-0000-0000-000000000000",
+ "resource": "api://botid-00000000-0000-0000-0000-000000000000"
+ }
+ ```
+
+ - If your app contains a bot and a tab, add the following code snippet:
+
+ ```json
+ "webApplicationInfo":
+ {
+ "id": "00000000-0000-0000-0000-000000000000",
+ "resource": "api://subdomain.example.com/botid-00000000-0000-0000-0000-000000000000"
+ }
+ ```
+
+ where,
+ - {Azure AD AppId} is the app ID you created when you registered your app in Azure AD. It's the GUID.
+ - {{Subdomain}.app ID URI} is the application ID URI that you registered when creating scope in Azure AD.
+
+4. Update the app ID from Azure AD in the **id** property.
+5. Update the subdomain URL in the following properties:
+ 1. `contentUrl`
+ 2. `configurationUrl`
+ 3. `validDomains`
+6. Save the Teams app manifest file.
+
+<br>
+<details>
+<summary>Here's an example of app manifest after it's updated</summary>
+
+```json
+{
+ "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.7/MicrosoftTeams.schema.json",
+ "manifestVersion": "1.7",
+ "version": "1.0",
+ "id": "00000000-0000-0000-0000-000000000000",
+ "packageName": "com.microsoft.teams.samples.auth",
+ "developer": {
+ "name": "Your Name Here",
+ "websiteUrl": "https://www.example.com",
+ "privacyUrl": "https://www.example.com/PrivacyStatement",
+ "termsOfUseUrl": "https://www.example.com/TermsOfUse"
+ },
+ "name": {
+ "short": "Teams AuthBot"
+ },
+ "description": {
+ "short": "Authentication sample for Microsoft Teams",
+ "full": "Authentication sample for Microsoft Teams"
+ },
+ "icons": {
+ "outline": "outline.png",
+ "color": "color.png"
+ },
+ "accentColor": "#F3F4F6",
+ "configurableTabs": [
+
+ ],
+ "staticTabs": [
+ {
+ "contentUrl": "https://<<BASE_URI_DOMAIN>>/tab/simple",
+ "entityId": "simpleAuth",
+ "name": "Simple Auth",
+ "scopes": [
+ "personal"
+ ]
+ },
+ {
+ "contentUrl": "https://<<BASE_URI_DOMAIN>>/tab/silent?loginHint={loginHint}&userObjectId={userObjectId}&tenantId={tid}",
+ "entityId": "silentAuth",
+ "name": "Silent Auth",
+ "scopes": [
+ "personal"
+ ]
+ },
+ {
+ "contentUrl": "https://<<BASE_URI_DOMAIN>>/tab/sso",
+ "entityId": "ssoAuth",
+ "name": "SSO Auth",
+ "scopes": [
+ "personal"
+ ]
+ }
+ ],
+ "bots": [
+ {
+ "botId": "<<REGISTERED_BOT_ID>>",
+ "scopes": [
+ "personal"
+ ]
+ }
+ ],
+ "permissions": [
+ "messageTeamMembers",
+ "identity"
+ ],
+ "validDomains": [
+ "<<BASE_URI_DOMAIN>>",
+ "token.botframework.com"
+ ],
+ "webApplicationInfo": {
+ "id": "<<REGISTERED_BOT_ID>>",
+ "resource": "api://<<BASE_URI_DOMAIN>>/<<REGISTERED_BOT_ID>>"
+ }
+}
+```
+
+</details>
+
+> [!NOTE]
+> During debug, you can use ngrok to test your app in Azure AD. In that case, you need to replace the subdomain in `api://subdomain.example.com/00000000-0000-0000-0000-000000000000` with the ngrok URL. You'll need to update the URL whenever your ngrok subdomain changes. For example, api://23c3-103-50-148-128.ngrok.io/bccfbe67-e08b-4ec1-a7fd-e0aaf41a097c.
+
+## Sideload and Preview in Teams
+
+You've configured the app to enable SSO. You can now sideload your app in Teams and preview it in Teams environment.
+
+To preview your app in Teams:
+
+1. Create an app package.
+
+ The app package is a zip file that contains the app manifest file and app icons.
+
+1. Open Teams.
+
+1. Select **Apps** > **Manage your apps** > **Upload an app**.
+
+ The options to upload an app appear.
+
+1. Select **Upload a custom app** to sideload the app into Teams.
+
+1. Select your app package zip file, and then select **Add**.
+
+ The app is sideloaded. The consent dialog appears to inform you of the permissions that may be required.
+
+1. Select **Continue**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/bot-consent.png" alt-text="Bot consent message" border="false":::
+
+ Teams opens the app and you can use it.
+
+ Congratulations! You've enabled SSO for your bot or message extension app.
+
+## SSO support in Developer Portal
+
+You can also upload your SSO-enabled app in Developer Portal. To enable SSO support in Developer Portal after you've imported it:
+
+1. Open [Developer Portal](https://dev.teams.microsoft.com/home).
+1. Select **Tools**, and from the list of apps that appears select your app to open it in Developer Portal.
+1. Select **Configure**.
+
+ The **Configure** page appears.
+
+1. Enter the messaging endpoint you configured in Azure AD as **Endpoint address**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/dev-portal-sso.png" alt-text="Developer Portal support for SSO in a bot app":::
+
+1. Select **Save**.
+
+Developer Portal would now support SSO for your app.
platform Bot Sso Overview https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/authentication/bot-sso-overview.md
+
+ Title: Overview to authentication using SSO in Teams with Azure AD
+description: Learn about Single sign-on (SSO) authentication in Teams and how to enable it in bots and message extension.
+
+ms.localizationpriority: high
+
+# Enable SSO for your app
+
+With Single sign-on (SSO) in Teams, app users have the advantage of using Teams to access bot or message extension apps. After logging into Teams using Microsoft or Microsoft 365 account, app users can use your app without needing to sign in again. Your app is available to app users on any device with access granted through Azure Active Directory (AD).
+
+This section covers SSO configuration required for bot and messaging extension apps.
+
+## SSO user experience in Teams
+
+App users sign in to Teams using either personal Microsoft account or Microsoft 365 account. You can take advantage of this and use SSO to authenticate and authorize the app users. Azure AD provides app users access to your bot or message extension app.
+
+- Teams authenticates and stores the identity of its app user.
+- Your bot uses the stored identity of the app user who is already validated by Teams.
+- The app user needs to give consent to Teams for using the identity to access your bot.
+- The app user can access the app on web, desktop, or mobile client.
+
+> [!NOTE]
+> App users can't give permission to some permission scopes, such as `Sites.ReadWrite.All`, which allows the app user to read and write to all SharePoint and OneDrive assets in the tenant. For such scopes, only the tenant administrator can grant consent on an app user's behalf.
+
+Now, let's see what happens at the backend during runtime to achieve SSO experience within Teams.
+
+## SSO in Teams at runtime
+
+Achieve SSO in a bot or message extension app by obtaining access token for the Teams app user who's currently signed in. This process involves the bot app client and server, Teams client, Bot Framework, and Azure AD. During this interaction, the app user must give consent to obtain the access token in a multi-tenant environment.
+
+The following image shows how SSO works when a Teams app user attempts to access the bot or message extension app:
++
+| # | Interaction | What's going on |
+| | | |
+| 1 | Teams client → Bot service | The message that app user sends is received by the Teams client, which sends it to the bot. <br> If the app user has previously signed in, a token is saved in the Bot Framework Token Store. The bot calls the Bot Framework Token Service which checks for an existing token for the app user in the Bot Framework Token Store. <br> • If the token exists, the app user is given access. <br> • If no token is available, the bot triggers the auth flow. |
+| 2 | Bot service → Bot Framework Token Service | The bot calls the Bot Framework Token Service to obtain a sign in link for the user. |
+| 3 | Bot Framework Token Service → Teams client | • **For bot app**: Bot Framework Token Service sends the request for sign-in link to the bot service, which forwards it to the Teams client in an OAuth card. <br> • **For message extension app**: Instead of the OAuth card, the Bot Framework Token Service sends an invoke request. |
+| 4 | Teams client → Bot service → Bot Framework Token Service → Azure AD | After the Teams client receives the OAuth card for the app user, if SSO is enabled, it sends a token exchange request for the app user back to the bot. The bot calls the Bot Framework Token Service, attempting to exchange the received token from Azure AD. |
+| 5 | Azure AD → Teams client | For the app user who's using the bot service for the first time, the token exchange can occur only after app user gives their consent. Teams client displays a message to the app user for giving consent. <br> In case the consent fails: <br> 1. The authentication falls back to the sign-in prompt and the app user must sign in to use the bot app. The sign-in button pops up in Teams client, and when app user selects it, the Azure AD sign-in page is rendered. <br> 2. The app user signs in and grants access to the bot service. |
+| 6 | Bot service → Bot Framework Token Service | The token for the app user is stored in the Bot Framework Token Store. |
+
+For a bot or a message extension app, the bot app sends an OAuth Card to Teams client. This card is used to get access token from Azure AD using `tokenExchangeResource`. Following app user's consent, Teams client sends the token received from Azure AD to the bot app using `tokenExchange`. The bot app can then parse the token to retrieve the app user's information, such as email address.
+
+> [!IMPORTANT]
+> A bot or message extension app can have more than one active endpoint. The first time app user would receive consent request for all active endpoints.
+
+## Enable SSO for a Teams app
+
+The bot and message extension apps use Bot Framework to handle communication with the app users.
+
+- **Bot app**: Also referred to as a chatbot or conversational bot, it's a service that runs simple and repetitive tasks for app users. Bots can be part of a larger application or be a standalone service.
+
+- **Message extension app**: It's a web service you host that can be invoked from within Teams client. It utilizes the messaging schema of a bot to ensure secure communication. You'll need to register your web service as a bot to enable SSO for your message extension app.
+
+This section describes the tasks involved in implementing SSO for a Teams bot or message extension app. To enable SSO for a Teams bot or message extension app:
+
+1. **Configure app with Azure AD**: Create an Azure AD app to generate an app ID and application ID URI. For generating an access token, you configure scopes and authorize trusted client applications. The configuration required in Azure AD for enabling SSO in a bot and message extension apps is the same. Create a bot resource and configure it's client secret, messaging endpoint, and OAuth connection to enable SSO.
+1. **Add code**: Add the code to handle access token to send this token to your app's server code in the Authorization header, and to validate the access token when it's received. The code required to enable SSO in a bot app is different from code required for a message extension app.
++
+ > [!NOTE]
+ > This section allows you to select the app for which you want to add code for enabling SSO.
+
+1. **Update Teams app manifest**: Update your Teams client app manifest with the app ID and application ID URI generated in Azure AD to allow Teams to request access tokens on behalf of your app. The update required in the manifest file is the same for bot and message extension apps.
+
+1. **Configure Graph scopes and permissions**: You can add more scopes to your app by extending your app with Microsoft Graph permissions and scopes.
+
+## Next step
+
+> [!div class="nextstepaction"]
+> [Configure your app in Azure AD](bot-sso-register-aad.md)
platform Bot Sso Register Aad https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/authentication/bot-sso-register-aad.md
+
+ Title: Configure your app in Azure AD
+description: Describes configuring your bot or message extension app with Azure AD for enabling SSO.
+
+ms.localizationpriority: high
+
+# Configure your app in Azure AD
+
+Azure AD provides app users access to your bot or message extension app. The app user who has signed into Teams can be given access to your app.
+
+## SSO configuration in Azure AD portal
+
+The bot and message extension apps use Bot Framework for communicating with app users and implementing authentication.
+
+To configure SSO for your bot or message extension app, you'll need to:
+
+- Configure bot resource in Azure AD
+- Configure app in Azure AD
+
+> [!NOTE]
+> Ensure that you've created an app and a bot resource in Azure AD.
+> - For more information about creating an app in Azure AD, see [Register a new app in Azure AD](../../../tabs/how-to/authentication/tab-sso-register-aad.md#to-register-a-new-app-in-azure-ad).
+> - For more information about creating and configuring your bot resource in Azure AD, see [Create Teams conversation bot](../../../sbs-teams-conversation-bot.yml).
+
+You can configure your bot resource and app in Azure AD for your bot or message extension app in one of the following two ways:
+
+- **Configure SSO using bot resource and configure Azure AD app**: You can start by configuring SSO for your bot resource, and enable SSO for your Azure AD app. You'll configure:
+
+ - For bot resource: Messaging endpoint and OAuth connection.
+
+ > [!NOTE]
+ > When you create your bot resource in Azure AD, you can select the option for creating a new app ID, or you can use an existing app ID if you've already registered your app in Azure AD.
+
+ - For Azure AD app: App ID URI, scope and permissions, trusted client IDs, access token version, client secret, and redirect URL.
+
+- **Configure SSO using Azure AD app and then configuring bot resource**: You can start by configuring your Azure AD app, and then use this app ID in the bot resource when you enable SSO for it. You'll configure:
+
+ - For Azure AD app: App ID URI, access token, trusted client IDs, access token version, client secret, and redirect URL.
+
+ - For bot resource: Messaging endpoint and OAuth connection.
+
+ > [!NOTE]
+ > Configure bot resource using the app ID generated by Azure AD when you registered your app.
+
+## Enable SSO in Azure AD
+
+By the end of this tutorial, you'll learn to configure:
+
+- Application ID
+- Bot ID
+- Access token
+ - Application ID URI
+ - Scope, permissions, and authorized client IDs
+ - Client secret
+ - Redirect URL
+- Messaging endpoint and OAuth connection
+
+Select one of the following two ways to configure SSO for your bot resource:
+
+# [Use bot resource and configure Azure AD app](#tab/botid)
+
+To enable SSO for your app in Azure AD:
+
+- **[Configure messaging endpoint](#configure-messaging-endpoint)**
+- **[Configure SSO for Azure AD app](#configure-sso-for-azure-ad-app)**:
+ - [Configure scope for the access token](#configure-scope-for-the-access-token)
+ - [Configure access token version](#configure-access-token-version)
+ - [Create client secret](#create-client-secret)
+ - [Configure redirect URL](#configure-redirect-url)
+- **[Configure OAuth connection](#configure-oauth-connection)**
+
+> [!IMPORTANT]
+> Ensure that when you create your bot resource, select the option to create a new app ID. You can also use an existing app ID, if you've already registered an app in Azure AD portal.
+
+## Configure messaging endpoint
+
+Messaging endpoint is where messages are sent to your bot. It enables communication with your bot.
+
+### To configure messaging endpoint for your bot resource
+
+1. Open the [Azure portal](https://ms.portal.azure.com/) on your web browser.
+ The Microsoft Azure Bot page opens.
+
+1. Enter the name of your bot resource in **Search** box, and select **Enter** to open it.
+
+1. Select **Settings** > **Configuration**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/bot-app-menu.png" alt-text="bot-config-menu.png":::
+
+ The **Configuration** page appears.
+
+1. Enter the messaging endpoint URL where your bot receives app user's messages.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/message-endpoint.png" alt-text="Define messaging endpoint where the bot interacts with the user." border="false":::
+
+1. Select **Apply**.
+
+ The messaging endpoint is configured.
+
+You've configured the messaging endpoint for your bot resource. Next, you must enable SSO for the Azure AD app.
+
+## Configure SSO for Azure AD app
+
+You must configure permissions and scopes, authorize client applications, update manifest, and create client secret for your Azure AD app. These configurations help to invoke SSO for your bot app.
+
+### Configure scope for the access token
+
+Configure scope (permission) options for sending access token to Teams client and authorizing trusted client applications to enable SSO.
+
+You need:
+
+- [To configure application ID URI](#to-configure-application-id-uri): Configure scope (permission) options for your app. You'll expose a web API and configure the application ID URI.
+- [To configure API scope](#to-configure-api-scope): Define scope for the API, and the users who can consent for a scope. You can let only admins provide consent for higher-privileged permissions.
+- [To configure authorized client application](#to-configure-authorized-client-application): Create authorized client IDs for applications that you want to pre-authorize. It allows the app user to access the app scopes (permissions) you've configured, without requiring any further consent. Pre-authorize only those client applications you trust, as your app users won't have the opportunity to decline consent.
+
+#### To configure application ID URI
+
+1. Open the [Azure portal](https://ms.portal.azure.com/) on your web browser.
+
+ The Microsoft Azure Bot page opens.
+
+1. Enter the name of your bot resource in **Search** box, and then select **Enter** to open it.
+
+1. Select **Settings** > **Configuration**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/bot-app-menu.png" alt-text="bot-config-menu.png":::
+
+ The **Configuration** page appears.
+
+1. Select **Manage**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/bot-config-manage.png" alt-text="Bot resource configuration" border="false":::
+
+ The Azure AD app page appears.
+
+ The new app ID (client ID) for the app appears on this page. Note and save this app ID. You'll need to update it in the Teams manifest later. If you used the ID of an existing app when you created the bot resource, then ID of that app appears in this page.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/aad-app-regd.png" alt-text="Bot app page":::
+
+1. Select **Manage** > **Expose an API** from the left pane.
+
+ The **Expose an API** page appears.
+
+1. Select **Set** to generate application ID URI.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/expose-an-api.png" alt-text="Set app ID URI." border="true":::
+
+ The section for setting application ID URI appears.
+
+1. Enter the application ID URI in the format explained here.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/set-app-id-uri.png" alt-text="Application ID URI" border="true":::
+
+ - The **Application ID URI** is pre-filled with app ID (GUID) in the format `api://{AppID}`.
+
+ > [!IMPORTANT]
+ >
+ > - **Standalone bot**: If you're building a standalone bot, enter the application ID URI as api://botid-{YourBotId}. Here, {YourBotId} is your Azure AD application ID.
+ > - **Application ID URI for app with multiple capabilities**: If you're building an app with a bot, a messaging extension, and a tab, enter the application ID URI as `api://fully-qualified-domain-name.com/BotId-{YourClientId}`, where the BotId is your bot app ID.
+ >
+ > - **Format for domain name**: Use lowercase letters for domain name. Don't use upper case.
+ >
+ > For example, to create an app service or web app with resource name, 'demoapplication':
+ >
+ > | If base resource name used is | URL will be... | Format is supported on... |
+ > | | | |
+ > | *demoapplication* | **<https://demoapplication.example.net>** | All platforms.|
+ > | *DemoApplication* | **<https://DemoApplication.example.net>** | Desktop, web, and iOS only. It isn't supported in Android. |
+ >
+ > Use the lowercase option *demoapplication* as base resource name.
+
+1. Select **Save**.
+
+ A message appears on the browser stating that the application ID URI was updated.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/app-id-uri-msg.png" alt-text="Application ID URI message" border="true":::
+
+ The application ID URI displays on the page.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/app-id-uri-added.png" alt-text="Application ID URI is updated" border="true":::
+
+1. Note and save the application ID URI. You'll need it for updating the Teams app manifest later.
+
+The application ID URI is configured. You can now define scope and permissions for your app.
+
+#### To configure API scope
+
+1. Select **+ Add a scope** in the **Scopes defined by this API** section.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/select-scope.png" alt-text="Select API scope" border="true":::
+
+ The **Add a scope** page appears.
+
+1. Enter the details for configuring scope.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/add-scope.png" alt-text="Add details for the scope" border="true":::
+
+ 1. Enter the scope name.
+ 2. Select the user who can give consent for this scope. The default option is **Admins only**.
+ 3. Enter the **Admin consent display name**.
+ 4. Enter the description for admin consent.
+ 5. Enter the **User consent display name**.
+ 6. Enter the user consent description.
+ 7. Select the **Enabled** option for state.
+ 8. Select **Add scope**.
+
+ > [!NOTE]
+ > For this tutorial, you can use openid profile `User.Read User.ReadBasic.All` as scope. This scope is suitable for using the [Code sample](bot-sso-code.md#code-sample). You can also add more Graph scopes and permissions. For more information, see [Extend your app with Microsoft Graph permissions and scopes](bot-sso-graph-api.md).
+
+ A message appears on the browser stating that the scope was added.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/scope-added-msg.png" alt-text="Scope added message displayed" border="true":::
+
+ > [!NOTE]
+ > The new scope you defined displays on the page. Ensure that you note and save the scope that you've configured. You'll need it to update OAuth connection later.
+
+The scope and permissions are now configured. Next, you must configure the authorized client applications for your Azure AD app.
+
+#### To configure authorized client application
+
+1. Move through the **Expose an API** page to the **Authorized client application** section, and select **+ Add a client application**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/auth-client-apps.png" alt-text="Authorized client application" border="true":::
+
+ The **Add a client application** page appears.
+
+1. Enter the appropriate Microsoft 365 client ID for the applications that you want to authorize for your appΓÇÖs web application.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/add-client-app.png" alt-text="Add a client ID" border="true":::
+
+ > [!NOTE]
+ >
+ > - The Microsoft 365 client IDs for mobile, desktop, and web applications for Teams, Office, and Outlook are the actual IDs that you must add.
+ > - If your app has a tab app, you'll need either web or SPA, as you can't have a mobile or desktop client application in Teams.
+
+1. Choose one of the following client IDs:
+
+ | Use client ID | For authorizing... |
+ | | |
+ | 1fec8e78-bce4-4aaf-ab1b-5451cc387264 | Teams mobile or desktop application |
+ | 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 | Teams web application |
+ | 4765445b-32c6-49b0-83e6-1d93765276ca | Office web application |
+ | 0ec893e0-5785-4de6-99da-4ed124e5296c | Office desktop application |
+ | d3590ed6-52b3-4102-aeff-aad2292ab01c | Outlook desktop and mobile application |
+ | bc59ab01-8403-45c6-8796-ac3ef710b3e3 | Outlook web application |
+
+1. Select the application ID URI you created for your app in **Authorized scopes** to add the scope to the web API you exposed.
+
+1. Select **Add application**.
+
+ A message appears on the browser stating that the authorized client app was added.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/update-app-auth-msg.png" alt-text="Client ID added message" border="true":::
+
+ The authorized app's client ID displays on the page.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/client-app-added.png" alt-text="Client ID added and displayed" border="true":::
+
+ > [!NOTE]
+ > You can authorize more than one client application. Repeat the steps of this procedure for configuring another authorized client application.
+
+You've successfully configured app scope, permissions, and client applications. Ensure that you note and save the application ID URI. Next, you configure the access token version.
+
+### Configure access token version
+
+You must define the access token version for your app in the Azure AD application manifest.
+
+#### To define the access token version
+
+1. Select **Manage** > **Manifest** from the left pane.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/azure-portal-manifest.png" alt-text="Azure AD portal Manifest" border="true":::
+
+ The Azure AD application manifest appears.
+
+1. Enter **2** as the value for the `accessTokenAcceptedVersion` property.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/azure-manifest-value.png" alt-text="Value for accepted access token version" border="true":::
+
+1. Select **Save**.
+
+ A message appears on the browser stating that the manifest was updated successfully.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/update-aad-manifest-msg.png" alt-text="Manifest updated":::
+
+You've updated the access token version. Next, you'll create a client secret for your app.
+
+### Create client secret
+
+A client secret is a string that the application uses to prove its identity when requesting a token.
+
+#### To create a client secret for your app
+
+1. Select **Manage** > **Certificates & secrets**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/client-secret-menu.png" alt-text="Client secret menu option":::
+
+ The **Certificates & secrets** page appears.
+
+2. Select **+ New client secret**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/client-secret.png" alt-text="Client secret page":::
+
+ The **Add a client secret** page appears.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/add-client-secret.png" alt-text="Add a client secret page" border="true":::
+
+ 1. Enter the description.
+ 1. Select the duration of validity for the secret.
+
+5. Select **Add**.
+
+ A message appears on the browser stating that the client secret was updated, and the client secret displays on the page.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/client-secret-added.png" alt-text="Client secret added":::
+
+6. Select the copy button next to the **Value** of client secret.
+7. Save the value that you copied. You'll need it later for updating code.
+
+ > [!IMPORTANT]
+ > Ensure that you copy the value of client secret right after you create it. The value is visible only at the time when the client secret is created, and it can't be viewed after that.
+
+You've configured the client secret. Next, you must configure the redirect URL.
+
+### Configure redirect URL
+
+Configuration for authentication depends on the platform or device where you want to target your app. You may need to configure redirect URIs, authentication settings, or platform-specific details.
+
+> [!NOTE]
+>
+> - If your bot app hasn't been granted IT admin consent, app users have to provide consent the first time they use your app on a different platform.
+> - Implicit grant is not required if SSO is enabled on a bot app.
+
+You can configure authentication for multiple platforms as long as the URL is unique.
+
+#### To configure redirect URL
+
+1. Open the app you registered in the [Azure portal](https://ms.portal.azure.com/).
+
+1. Select **Manage** > **Authentication** from the left pane.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/azure-portal-platform.png" alt-text="Authenticate for platforms" border="true":::
+
+ The **Platform configurations** page appears.
+
+1. Select **+ Add a platform**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/add-platform.png" alt-text="Add a platforms" border="true":::
+
+ The **Configure platforms** page appears.
+
+1. Select the platform that you want to configure for your app. You can choose the platform type from web or SPA.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/configure-platform.png" alt-text="Select web platform" border="true":::
+
+ <!--You can configure multiple platforms for a particular platform type. Ensure that the redirect URI is unique for every platform you configure.-->
+
+ The **Configure Web** page appears.
+
+ > [!NOTE]
+ > The configurations will be different based on the platform you select.
+
+1. Enter the configuration details for the platform.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/config-web-platform.png" alt-text="Configure web platform" border="true":::
+
+ 1. Enter the redirect URI. The URI should be unique.
+
+ > [!NOTE]
+ > The URL mentioned in **Redirect URIs** is an example.
+
+ 1. Enter the front-channel log-out URL.
+ 1. Select the tokens you want Azure AD to send for your app.
+
+1. Select **Configure**.
+
+ The platform is configured and displayed in the **Platform configurations** page.
+
+The Azure AD app configuration is complete, and now you must enable SSO support for your bot resource by configuring OAuth connection.
+
+## Configure OAuth connection
+
+For a bot to support SSO, you must update its OAuth connection settings. This process associates the bot with app details that you configured for your Azure AD app:
+
+- Azure AD app ID, which is the client ID
+- Tenant ID
+- Scope and permissions
+
+With the app (client) ID and client secret provided, the Bot Framework Token Store exchanges the token for a graph token with defined permissions.
+
+### To update OAuth connection
+
+1. Open the [Azure portal](https://ms.portal.azure.com/) on your web browser.
+ The Microsoft Azure Bot page opens.
+
+1. Enter the name of your Azure AD app in **Search** box, and open your app.
+
+1. Select **Settings** > **Configuration**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/bot-configuration.png" alt-text="Configure OAUth settings for your bot app" border="false":::
+
+ The **Configuration** page appears.
+
+1. Move through the **Configuration** page and select **Add OAuth Connection Settings**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/bot-oauth-connection.png" alt-text="OAuth connection button":::
+
+ The **New Connection Setting** page appears.
+
+1. Enter the OAuth configuration settings for the Azure bot.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/new-config-setting.png" alt-text="OAuth configuration settings" border="true":::
+
+ 1. Enter a name for the configuration setting.
+ 1. Select the service provider.
+
+ The remaining configuration details appear.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/new-config-setting-b.png" alt-text="Additional fields for OAuth configuration " border="true":::
+
+ 1. Enter the app (client) ID for the Azure AD app.
+ 1. Enter the client secret that you've created for your bot.
+ 1. Enter the application ID URI of your bot in the **Token Exchange URL**.
+ 1. Enter the tenant ID.
+ 1. Enter the scope that you defined when you configured the scope and permissions.
+
+1. Select **Save**.
+1. Select **Apply**.
+
+ After you've configured the OAuth connection, you can select **Test connection** to check if the OAuth connection is successful.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/test-oauth.png" alt-text="Test OAuth connection for your bot resource":::
+
+ If the connection isn't successful, Azure AD, displays an error. You can verify all configurations and test again.
+
+Congratulations! You've completed the following app configurations in Azure AD required to enable SSO for your bot app:
+
+- Application ID
+- Bot ID
+- Access token
+ - Application ID URI
+ - Scope, permissions, and authorized client IDs
+ - Client secret
+ - Redirect URL
+- Messaging endpoint and OAuth connection
+
+# [Use Azure AD app and then configure bot resource](#tab/windows)
+
+To create and configure your app for enabling SSO in Azure AD:
+
+- [**Configure your Azure AD app for SSO**](#configure-your-azure-ad-app-for-sso)
+ - [Configure scope for access token](#configure-scope-for-access-token)
+ - [Configure the access token version](#configure-the-access-token-version)
+ - [Create client secret for your app](#create-client-secret-for-your-app)
+ - [Configure redirect URL for your app](#configure-redirect-url-for-your-app)
+- [**Configure bot resource in Azure AD**](#configure-bot-resource-in-azure-ad)
+ - [Configure messaging endpoint for your bot resource](#configure-messaging-endpoint-for-your-bot-resource)
+ - [Configure OAuth connection for your bot resource](#configure-oauth-connection-for-your-bot-resource)
+
+## Configure your Azure AD app for SSO
+
+You must configure permissions and scopes, authorize client applications, update manifest, and create client secret for your Azure AD app. These configurations help invoke SSO for your bot app.
+
+> [!IMPORTANT]
+> Ensure that you've [registered your app](../../../tabs/how-to/authentication/tab-sso-register-aad.md#to-register-a-new-app-in-azure-ad) in Azure AD. At registration, Azure AD generates a new app ID that you must note. You'll need to update it later in the Teams app manifest file.
+
+### Configure scope for access token
+
+You must configure scope (permission) options for your Azure AD app. You need it for sending access token to Teams client and authorize trusted client applications.
+
+To configure scope and authorize trusted client applications, you'll need:
+
+- [To configure application ID URI for your app](#to-configure-application-id-uri-for-your-app): Configure scope (permission) options for your app. You'll expose a web API and configure the application ID URI.
+- [To configure API scope for your app](#to-configure-api-scope-for-your-app): Define scope for the API and the users who can consent for a scope. You can let only admins provide consent for higher-privileged permissions.
+- [To configure an authorized client application](#to-configure-an-authorized-client-application): Create authorized client IDs for applications that you want to pre-authorize. It allows the app user to access the app scopes (permissions) you've configured, without requiring any further consent. Pre-authorize only those client applications you trust as your app users won't have the opportunity to decline consent.
+
+#### To configure application ID URI for your app
+
+1. Open the [Azure portal](https://ms.portal.azure.com/) on your web browser.
+
+ The Microsoft Azure Bot page opens.
+
+1. Enter the name of your bot resource in **Search** box, and then select **Enter** to open it.
+
+1. Select **Settings** > **Configuration**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/bot-app-menu.png" alt-text="Configuration menu":::
+
+ The **Configuration** page appears.
+
+1. Select **Manage**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/bot-config-manage.png" alt-text="Bot resource configuration" border="false":::
+
+ The Azure AD app page appears.
+
+ The new app ID (client ID) for the app appears on this page. Note and save this app ID. You'll need to update it in the Teams manifest later. If you used the ID of an existing app when you created the bot resource, then ID of that app appears in this page.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/aad-app-regd.png" alt-text="Bot app page":::
+
+1. Select **Manage** > **Expose an API** from the left pane.
+
+ The **Expose an API** page appears.
+
+1. Select **Set** to generate application ID URI.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/expose-an-api.png" alt-text="Set app ID URI." border="true":::
+
+ The section for setting application ID URI appears.
+
+1. Enter the application ID URI in the format explained here.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/set-app-id-uri.png" alt-text="Application ID URI" border="true":::
+
+ - The **Application ID URI** is pre-filled with app ID (GUID) in the format `api://{AppID}`.
+
+ > [!IMPORTANT]
+ >
+ > - **Standalone bot**: If you're building a standalone bot, enter the application ID URI as api://botid-{YourBotId}. Here, {YourBotId} is your Azure AD application ID.
+ > - **Application ID URI for app with multiple capabilities**: If you're building an app with a bot, a messaging extension, and a tab, enter the application ID URI as `api://fully-qualified-domain-name.com/BotId-{YourClientId}`, where the BotID is your bot app ID.
+ >
+ > - **Format for domain name**: Use lowercase letters for domain name. Don't use upper case.
+ >
+ > For example, to create an app service or web app with resource name, 'demoapplication':
+ >
+ > | If base resource name used is | URL will be... | Format is supported on... |
+ > | | | |
+ > | *demoapplication* | **<https://demoapplication.example.net>** | All platforms.|
+ > | *DemoApplication* | **<https://DemoApplication.example.net>** | Desktop, web, and iOS only. It isn't supported in Android. |
+ >
+ > Use the lowercase option *demoapplication* as base resource name.
+
+1. Select **Save**.
+
+ A message appears on the browser stating that the application ID URI was updated.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/app-id-uri-msg.png" alt-text="Application ID URI message" border="true":::
+
+ The application ID URI displays on the page.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/app-id-uri-added.png" alt-text="Application ID URI is updated" border="true":::
+
+1. Note and save the application ID URI. You'll need it for updating the Teams app manifest later.
+
+The application ID URI is configured. You can now define scope and permissions for your app.
+
+#### To configure API scope for your app
+
+1. Select **+ Add a scope** in the **Scopes defined by this API** section.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/select-scope.png" alt-text="Select API scope" border="true":::
+
+ The **Add a scope** page appears.
+
+1. Enter the details for configuring scope.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/add-scope.png" alt-text="Add details for the scope" border="true":::
+
+ 1. Enter the scope name.
+ 2. Select the user who can give consent for this scope. The default option is **Admins only**.
+ 3. Enter the **Admin consent display name**.
+ 4. Enter the description for admin consent.
+ 5. Enter the **User consent display name**.
+ 6. Enter the user consent description.
+ 7. Select the **Enabled** option for state.
+ 8. Select **Add scope**.
+
+ > [!NOTE]
+ > For this tutorial, you can use openid profile User.Read User.ReadBasic.All as scope. This scope is suitable for using the [Code sample](bot-sso-code.md#code-sample). You can also add more Graph scopes and permissions. For more information, see [Extend your app with Microsoft Graph permissions and scopes](bot-sso-graph-api.md).
+
+ A message appears on the browser stating that the scope was added.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/scope-added-msg.png" alt-text="Scope added message displayed" border="true":::
+
+ > [!NOTE]
+ > The new scope you defined displays on the page. Ensure that you note and save the scope that you've configured. You'll need it to update OAuth connection later.
+
+The scope and permissions are now configured. Next, you must configure the authorized client applications for your Azure AD app.
+
+#### To configure an authorized client application
+
+1. Move through the **Expose an API** page to the **Authorized client application** section, and select **+ Add a client application**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/auth-client-apps.png" alt-text="Authorized client application" border="true":::
+
+ The **Add a client application** page appears.
+
+1. Enter the appropriate Microsoft 365 client ID for the applications that you want to authorize for your appΓÇÖs web application.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/add-client-app.png" alt-text="Add a client ID" border="true":::
+
+ > [!NOTE]
+ >
+ > - The Microsoft 365 client IDs for mobile, desktop, and web applications for Teams, Office, and Outlook are the actual IDs that you must add.
+ > - If your app has a tab app, you'll need either web or SPA, as you can't have a mobile or desktop client application in Teams.
+
+1. Choose one of the following client IDs:
+
+ | Use client ID | For authorizing... |
+ | | |
+ | 1fec8e78-bce4-4aaf-ab1b-5451cc387264 | Teams mobile or desktop application |
+ | 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 | Teams web application |
+ | 4765445b-32c6-49b0-83e6-1d93765276ca | Office web application |
+ | 0ec893e0-5785-4de6-99da-4ed124e5296c | Office desktop application |
+ | d3590ed6-52b3-4102-aeff-aad2292ab01c | Outlook desktop and mobile application |
+ | bc59ab01-8403-45c6-8796-ac3ef710b3e3 | Outlook web application |
+
+1. Select the application ID URI you created for your app in **Authorized scopes** to add the scope to the web API you exposed.
+
+1. Select **Add application**.
+
+ A message appears on the browser stating that the authorized client app was added.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/update-app-auth-msg.png" alt-text="Client ID added message" border="true":::
+
+ The authorized app's client ID displays on the page.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/client-app-added.png" alt-text="Client ID added and displayed" border="true":::
+
+ > [!NOTE]
+ > You can authorize more than one client application. Repeat the steps of this procedure for configuring another authorized client application.
+
+You've successfully configured app scope, permissions, and client applications. Ensure that you note and save the application ID URI. Next, you configure the access token version.
+
+### Configure the access token version
+
+You must define the access token version for your app in the Azure AD application manifest.
+
+#### To define access token version
+
+1. Select **Manage** > **Manifest** from the left pane.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/azure-portal-manifest.png" alt-text="Azure AD portal Manifest" border="true":::
+
+ The Azure AD application manifest appears.
+
+1. Enter **2** as the value for the `accessTokenAcceptedVersion` property.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/azure-manifest-value.png" alt-text="Value for accepted access token version" border="true":::
+
+1. Select **Save**.
+
+ A message appears on the browser stating that the manifest was updated successfully.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/update-aad-manifest-msg.png" alt-text="Manifest updated":::
+
+You've updated the access token version. Next step is to create a client secret for your app next.
+
+### Create client secret for your app
+
+A client secret is a string that the application uses to prove its identity when requesting a token.
+
+#### To create a client secret
+
+1. Select **Manage** > **Certificates & secrets**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/client-secret-menu.png" alt-text="Client secret menu option":::
+
+ The **Certificates & secrets** page appears.
+
+2. Select **+ New client secret**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/client-secret.png" alt-text="Client secret page":::
+
+ The **Add a client secret** page appears.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/add-client-secret.png" alt-text="Add a client secret page" border="true":::
+
+ 1. Enter the description.
+ 1. Select the duration of validity for the secret.
+
+5. Select **Add**.
+
+ A message appears on the browser stating that the client secret was updated, and the client secret displays on the page.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/client-secret-added.png" alt-text="Client secret added":::
+
+6. Select the copy button next to the **Value** of client secret.
+7. Save the value that you copied. You'll need it later for updating code.
+
+ > [!IMPORTANT]
+ > Ensure that you copy the value of client secret right after you create it. The value is visible only at the time when the client secret is created, and it can't be viewed after that.
+
+### Configure redirect URL for your app
+
+Configuration for authentication depends on the platform or device where you want to target your app. You may need to configure redirect URIs, authentication settings, or platform-specific details.
+
+> [!NOTE]
+>
+> - If your bot app hasn't been granted IT admin consent, app users have to provide consent the first time they use your app on a different platform.
+> - Implicit grant is not required if SSO is enabled on a bot app.
+
+You can configure authentication for multiple platforms as long as the URL is unique.
+
+#### To configure redirect URL for your app
+
+1. Open the app you registered in the [Azure portal](https://ms.portal.azure.com/).
+
+1. Select **Manage** > **Authentication** from the left pane.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/azure-portal-platform.png" alt-text="Authenticate for platforms" border="true":::
+
+ The **Platform configurations** page appears.
+
+1. Select **+ Add a platform**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/add-platform.png" alt-text="Add a platforms" border="true":::
+
+ The **Configure platforms** page appears.
+
+1. Select the platform that you want to configure for your app. You can choose the platform type from web or SPA.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/configure-platform.png" alt-text="Select web platform" border="true":::
+
+ The **Configure Web** page appears.
+
+ > [!NOTE]
+ > The configurations will be different based on the platform you select.
+
+1. Enter the configuration details for the platform.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/config-web-platform.png" alt-text="Configure web platform" border="true":::
+
+ 1. Enter the redirect URI. The URI should be unique.
+
+ > [!NOTE]
+ > The URL mentioned in **Redirect URIs** is an example.
+
+ 1. Enter the front-channel log-out URL.
+ 1. Select the tokens you want Azure AD to send for your app.
+
+1. Select **Configure**.
+
+ The platform is configured and displayed in the **Platform configurations** page.
+
+The configuration for Azure AD app is complete, and now you can configure your bot resource for enabling SSO.
+
+## Configure bot resource in Azure AD
+
+Before you enable SSO for your bot app, you must create and configure your bot resource in Azure AD. For more information, see [Create Teams conversation bot](../../../sbs-teams-conversation-bot.yml).
+
+> [!NOTE]
+> Ensure that when you create your bot resource, you select the application ID of your Azure AD app that you registered.
+
+To enable SSO for your bot resource:
+
+- [Configure messaging endpoint for your bot resource](#configure-messaging-endpoint-for-your-bot-resource)
+- [Configure OAuth connection for your bot resource](#configure-oauth-connection-for-your-bot-resource)
+
+### Configure messaging endpoint for your bot resource
+
+Messaging endpoint is where messages are sent to your bot. It enables communication with your bot.
+
+#### To configure messaging endpoint
+
+1. Open the [Azure portal](https://ms.portal.azure.com/) on your web browser.
+ The Microsoft Azure Bot page opens.
+
+1. Enter the name of your bot resource in **Search** box, and select **Enter** to open it.
+
+1. Select **Settings** > **Configuration**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/bot-app-menu.png" alt-text="bot-config-menu.png":::
+
+ The **Configuration** page appears.
+
+1. Enter the messaging endpoint URL where your bot receives app user's messages.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/message-endpoint.png" alt-text="Define messaging endpoint where the bot interacts with the user." border="false":::
+
+1. Select **Apply**.
+
+ The messaging endpoint is configured.
+
+Now, you must configure the OAuth connection to enable SSO for your bot resource.
+
+### Configure OAuth connection for your bot resource
+
+For a bot to support SSO, you must update its OAuth connection settings. This process associates the bot with app details that you configured for your Azure AD app:
+
+- Azure AD app ID, which is the client ID
+- Tenant ID
+- Scope and permissions
+
+With the app (client) ID and client secret provided, the Bot Framework Token Store exchanges the token for a graph token with defined permissions.
+
+#### To update OAuth connection for your bot resource
+
+1. Open the [Azure portal](https://ms.portal.azure.com/) on your web browser.
+ The Microsoft Azure Bot page opens.
+
+1. Enter the name of your Azure AD app in **Search** box, and open your app.
+
+1. Select **Settings** > **Configuration**.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/bot-configuration.png" alt-text="Configure OAUth settings for your bot app" border="false":::
+
+ The **Configuration** page appears.
+
+1. Move through the **Configuration** page and select **Add OAuth Connection Settings**.
+
+ The **New Connection Setting** page appears.
+
+1. Enter the OAuth configuration settings for the Azure bot.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/new-config-setting.png" alt-text="OAuth configuration settings" border="true":::
+
+ 1. Enter a name for the configuration setting.
+ 1. Select the service provider.
+
+ The remaining configuration details appear.
+
+ :::image type="content" source="../../../assets/images/authentication/teams-sso-bots/new-config-setting-b.png" alt-text="Additional fields for OAuth configuration " border="true":::
+
+ 1. Enter the client ID that was generated when you created the bot app.
+ 1. Enter the client secret that you've created for your bot.
+ 1. Enter the application ID URI of your bot in the **Token Exchange URL**.
+ 1. Enter the tenant ID.
+ 1. Enter the scope that you defined when you configured the permissions.
+
+ > [!NOTE]
+ > For this tutorial, you can use openid profile User.Read User.ReadBasic.All as scope. This scope is suitable for using the [Code sample](bot-sso-code.md#code-sample).
+
+1. Select **Save**.
+1. Select **Apply**.
+
+After you've configured the OAuth connection, you can select **Test connection** to check if the OAuth connection is successful.
++
+If the connection isn't successful, Azure AD, displays an error. You can verify all configurations and test again.
+
+Congratulations! You've completed the following app configurations in Azure AD required to enable SSO for your bot app:
+
+- Application ID
+- Bot ID
+- Access token
+ - Application ID URI
+ - Scope, permissions, and authorized client IDs
+ - Client secret
+ - Redirect URL
+- Messaging endpoint and OAuth connection
+++
+## Next step
+
+> [!div class="nextstepaction"]
+> [Add code to enable SSO](bot-sso-code.md)
platform Conversation Basics https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/conversations/conversation-basics.md
Each message in a bot conversation is an `Activity` object of type `messageType:
A bot can also send proactive messages to users. A proactive message is any message sent by a bot that isn't in response to a request from a user. You can format your bot messages to include rich cards that include interactive elements, such as buttons, text, images, audio, video, and so on. Bot can dynamically update messages after sending them, instead of having your messages as static snapshots of data. Messages can also be deleted using the Bot Framework's `DeleteActivity` method. The outgoing request to the bot shows conversation ID and tenant ID in the headers. The workflow bot is a type of conversational bot, which interacts with the users in the Adaptive Card. You can customize how the bot sends the Adaptive Card to the users.
+## Add SSO authentication to your conversation bots
+
+You can add single sign-on authentication to your conversation bot using the following steps:
+
+* [Create Teams conversation bot](../../../sbs-teams-conversation-bot.yml)
+* [Configure your bot app in Azure AD](/bots/how-to/authentication/bot-sso-register-aad)
+ ## Next step > [!div class="nextstepaction"]
platform What Are Bots https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/what-are-bots.md
With Microsoft Graph APIs for calls and online meetings, Teams apps can now inte
You can use the Teams bot APIs to get information for members of a chat or team. See [changes to Teams bot APIs for fetching team or chat members](~/resources/team-chat-member-api-changes.md).
+## Add SSO authentication to your conversation bots
+
+You can add single sign-on authentication to your conversation bot using the following steps:
+
+* [Create Teams conversation bot](../sbs-teams-conversation-bot.yml)
+* [Configure your bot app in Azure AD](/bots/how-to/authentication/bot-sso-register-aad)
+ <! TBD: For quick scanning, see if the above information can be itemized as a list. >
platform Authentication https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/concepts/authentication/authentication.md
Enable authentication with SSO or third party OAuth IdPs in your tab app, bot ap
:::row-end::: :::row::: :::column span="1":::
- :::image type="content" source="../../assets/images/authentication/bot-sso-icon.png" alt-text="SSO for bot app" link="../../bots/how-to/authentication/auth-aad-sso-bots.md":::
+ :::image type="content" source="../../assets/images/authentication/bot-sso-icon.png" alt-text="SSO for bot app" link="../../bots/how-to/authentication/bot-sso-overview.md":::
++ :::column-end::: :::column span="1"::: <br>
Enable authentication with SSO or third party OAuth IdPs in your tab app, bot ap
:::row-end::: :::row::: :::column span="1":::
- :::image type="content" source="../../assets/images/authentication/mex-sso-icon.png" alt-text="SSO for messaging extension app" link="../../messaging-extensions/how-to/enable-SSO-auth-me.md":::
+ :::image type="content" source="../../assets/images/authentication/mex-sso-icon.png" alt-text="SSO for messaging extension app" link="../../bots/how-to/authentication/bot-sso-overview.md":::
:::column-end::: :::column span="1"::: <br>
Enable authentication with SSO or third party OAuth IdPs in your tab app, bot ap
:::column-end::: :::row-end:::
-> [!NOTE]
-> The Silent authentication page is moved to the Resources module. For more information, see [Silent authentication](../../tabs/how-to/authentication/auth-silent-aad.md).
- ## See also - [Enable single sign-on in a tab app](../../tabs/how-to/authentication/tab-sso-overview.md)
platform Msgex Sso Code https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/includes/messaging-extensions/msgex-sso-code.md
+> [!NOTE]
+> `OnTeamsMessagingExtensionQueryAsync` and `OnTeamsAppBasedLinkQueryAsync` from the `TeamsMessagingExtensionsSearchAuthConfigBot.cs` file are the only SSO handlers that are supported. Other SSO handlers aren't supported.
+
+This section covers:
+
+1. [Update development environment variables](#update-development-environment-variables)
+1. [Add code to request a token](#add-code-to-request-a-token)
+1. [Add code to receive the token](#add-code-to-receive-the-token)
+1. [Add token to Bot Framework Token Store](#add-token-to-bot-framework-token-store)
+1. [Handle app user log out](#handle-app-user-log-out)
+
+## Update development environment variables
+
+You've configured client secret and OAuth connection setting for the app in Azure AD. You must configure your app code with these variables.
+
+To update the development environment variables:
+
+1. Open the app project.
+1. Open the `./env` file for your project.
+1. Update the following variables:
+
+ - For `MicrosoftAppId`, update the Bot registration ID from Azure AD.
+ - For `MicrosoftAppPassword`, update the Bot registration client secret.
+ - For `ConnectionName`, update the name of the OAuth connection you configured in Azure AD.
+ - For `MicrosoftAppTenantId`, update the tenant ID.
+
+1. Save the file.
+
+You've now configured the required environment variables for your bot app and SSO. Next, add the code for handling tokens.
+
+## Add code to request a token
+
+The request to get the token is a POST message request using the existing message schema. It's included in the attachments of an OAuthCard. The schema for the OAuthCard class is defined in [Microsoft Bot Schema 4.0](/dotnet/api/microsoft.bot.schema.oauthcard?view=botbuilder-dotnet-stable&preserve-view=true). Teams refreshes the token if the `TokenExchangeResource` property is populated on the card. For the Teams channel, only the `Id` property, which uniquely identifies a token request, is honored.
+
+>[!NOTE]
+> The Microsoft Bot Framework `OAuthPrompt` or the `MultiProviderAuthDialog` is supported for SSO authentication.
+
+To update your app's code:
+
+1. Add code snippet for `TeamsSSOTokenExchangeMiddleware`.
+
+ # [csharp](#tab/cs1)
+
+ Add the following code snippet to `AdapterWithErrorHandler.cs` (or the equivalent class in your app's code):
+
+ ```csharp
+ base.Use(new TeamsSSOTokenExchangeMiddleware(storage, configuration["ConnectionName"]));
+ ```
+
+ # [JavaScript](#tab/js1)
+
+ Add the following code snippet to `index.js` (or the equivalent class in your app's code):
+
+ ```JavaScript
+ const {TeamsSSOTokenExchangeMiddleware} = require('botbuilder');
+ const tokenExchangeMiddleware = new TeamsSSOTokenExchangeMiddleware(memoryStorage, env.connectionName);
+ adapter.use(tokenExchangeMiddleware);
+ ```
+
+
+
+ >[!NOTE]
+ > You might receive multiple responses for a given request if the user has multiple active endpoints. You must eliminate all duplicate or redundant responses with the token. For more information about signin/tokenExchange, see [TeamsSSOTokenExchangeMiddleware Class](/python/api/botbuilder-core/botbuilder.core.teams.teams_sso_token_exchange_middleware.teamsssotokenexchangemiddleware?view=botbuilder-py-latest#remarks&preserve-view=true).
+
+1. Use the following code snippet for requesting a token.
+
+ # [csharp](#tab/cs2)
+
+ After you add the `AdapterWithErrorHandler.cs`, your code should be as shown below:
+
+ ```csharp
+ public class AdapterWithErrorHandler : CloudAdapter
+ {
+ public AdapterWithErrorHandler(
+ IConfiguration configuration,
+ IHttpClientFactory httpClientFactory,
+ ILogger<IBotFrameworkHttpAdapter> logger,
+ IStorage storage,
+ ConversationState conversationState)
+ : base(configuration, httpClientFactory, logger)
+ {
+ base.Use(new TeamsSSOTokenExchangeMiddleware(storage, configuration["ConnectionName"]));
+
+ OnTurnError = async (turnContext, exception) =>
+ {
+ // Log any leaked exception from the application.
+ // NOTE: In production environment, you should consider logging this to
+ // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how
+ // to add telemetry capture to your bot.
+ logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
+
+ // Send a message to the user.
+ await turnContext.SendActivityAsync("The bot encountered an error or bug.");
+ await turnContext.SendActivityAsync("To continue to run this bot, please fix the bot source code.");
+
+ if (conversationState != null)
+ {
+ try
+ {
+ // Delete the conversationState for the current conversation to prevent the
+ // bot from getting stuck in an error-loop caused by being in a bad state.
+ // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
+ await conversationState.DeleteAsync(turnContext);
+ }
+ catch (Exception e)
+ {
+ logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
+ }
+ }
+
+ // Send a trace activity, which will be displayed in the Bot Framework Emulator.
+ await turnContext.TraceActivityAsync(
+ "OnTurnError Trace",
+ exception.Message,
+ "https://www.botframework.com/schemas/error",
+ "TurnError");
+ };
+ }
+ }
+ ```
+
+ # [JavaScript](#tab/js2)
+
+ After you add the code to `index.js`, your code should be as shown below:
+
+ ```JavaScript
+ // index.js is used to setup and configure your bot.
+
+ // Import required packages.
+ const path = require('path');
+
+ // Read botFilePath and botFileSecret from .env file.
+ const ENV_FILE = path.join(__dirname, '.env');
+ require('dotenv').config({ path: ENV_FILE });
+
+ const restify = require('restify');
+
+ // Import required bot services.
+ // See https://aka.ms/bot-services to learn more about the different parts of a bot.
+ const {
+ CloudAdapter,
+ ConversationState,
+ MemoryStorage,
+ UserState,
+ ConfigurationBotFrameworkAuthentication,
+ TeamsSSOTokenExchangeMiddleware
+ } = require('botbuilder');
+
+ const { TeamsBot } = require('./bots/teamsBot');
+ const { MainDialog } = require('./dialogs/mainDialog');
+ const { env } = require('process');
+
+ const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(process.env);
+
+ var conname = env.connectionName;
+
+ console.log(`\n${ conname } is the con name`);
+
+ // Create adapter.
+ // See https://aka.ms/about-bot-adapter to learn more about how bots work.
+ const adapter = new CloudAdapter(botFrameworkAuthentication);
+ const memoryStorage = new MemoryStorage();
+ const tokenExchangeMiddleware = new TeamsSSOTokenExchangeMiddleware(memoryStorage, env.connectionName);
+
+ adapter.use(tokenExchangeMiddleware);
+ adapter.onTurnError = async (context, error) => {
+ // This check writes out errors to console log .vs. app insights.
+ // NOTE: In production environment, you should consider logging this to Azure application insights. See https://aka.ms/bottelemetry for telemetry configuration instructions.
+ console.error(`\n [onTurnError] unhandled error: ${ error }`);
+
+ // Send a trace activity, which will be displayed in Bot Framework Emulator.
+ await context.sendTraceActivity(
+ 'OnTurnError Trace',
+ `${ error }`,
+ 'https://www.botframework.com/schemas/error',
+ 'TurnError'
+ );
+
+ // Send a message to the user.
+ await context.sendActivity('The bot encountered an error or bug.');
+ await context.sendActivity('To continue to run this bot, please fix the bot source code.');
+ // Clear out state.
+ await conversationState.delete(context);
+ };
+
+ // Define the state store for your bot.
+ // See https://aka.ms/about-bot-state to learn more about using MemoryStorage.
+ // A bot requires a state storage system to persist the dialog and user state between messages.
+ //const memoryStorage = new MemoryStorage();
+
+ // Create conversation and user state with in-memory storage provider.
+ const conversationState = new ConversationState(memoryStorage);
+ const userState = new UserState(memoryStorage);
+
+ // Create the main dialog.
+ const dialog = new MainDialog();
+ // Create the bot that will handle incoming messages.
+ const bot = new TeamsBot(conversationState, userState, dialog);
+
+ // Create HTTP server.
+ const server = restify.createServer();
+ server.use(restify.plugins.bodyParser());
+
+ server.listen(process.env.port || process.env.PORT || 3978, function() {
+ console.log(`\n${ server.name } listening to ${ server.url }`);
+ console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
+ console.log('\nTo talk to your bot, open the emulator select "Open Bot"');
+ });
+
+ // Listen for incoming requests.
+ server.post('/api/messages', async (req, res) => {
+ // Route received a request to adapter for processing.
+ await adapter.process(req, res, (context) => bot.run(context));
+ });
+
+ ```
+++
+### Consent dialog for getting access token
+
+If the app user is using your app for the first time, they may be required to consent for SSO authentication.
++
+When the app user selects the user name, the permission is granted and they can use the app.
++
+The consent dialog that appears is for open-id scopes defined in Azure AD. The app user must give consent only once. After consenting, the app user can access and use your message extension app for the granted permissions and scopes.
+
+> [!IMPORTANT]
+> Scenarios where consent dialogs are not needed:
+>
+> - If the tenant administrator has granted consent on behalf of the tenant, app users don't need to be prompted for consent at all. This means that the app users don't see the consent dialogs and can access the app seamlessly.
+
+If you encounter any errors, see [Troubleshoot SSO authentication in Teams](~/tabs/how-to/authentication/tab-sso-troubleshooting.md).
+
+## Add code to receive the token
+
+The response with the token is sent through an invoke activity with the same schema as other invoke activities that the bots receive today. The only difference is the invoke name,
+sign in/tokenExchange, and the **value** field. The **value** field contains the **Id**, a string of the initial request to get the token and the **token** field, a string value including the token.
+
+Use the following code snippet example to invoke response:
+
+# [csharp](#tab/cs3)
+
+```csharp
+public MainDialog(IConfiguration configuration, ILogger<MainDialog> logger)
+ : base(nameof(MainDialog), configuration["ConnectionName"])
+ {
+ AddDialog(new OAuthPrompt(
+ nameof(OAuthPrompt),
+ new OAuthPromptSettings
+ {
+ ConnectionName = ConnectionName,
+ Text = "Please Sign In",
+ Title = "Sign In",
+ Timeout = 300000, // User has 5 minutes to login (1000 * 60 * 5)
+ EndOnInvalidMessage = true
+ }));
+
+ AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
+
+ AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
+ {
+ PromptStepAsync,
+ LoginStepAsync,
+ }));
+
+ // The initial child Dialog to run.
+ InitialDialogId = nameof(WaterfallDialog);
+ }
++
+private async Task<DialogTurnResult> PromptStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
+ {
+ return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken);
+ }
+
+private async Task<DialogTurnResult> LoginStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
+ {
+
+ var tokenResponse = (TokenResponse)stepContext.Result;
+ if (tokenResponse?.Token != null)
+ {
+ var token = tokenResponse.Token;
+
+ // On successful login, the token contains sign in token.
+ }
+ else
+ {
+ await stepContext.Context.SendActivityAsync(MessageFactory.Text("Login was not successful please try again."), cancellationToken);
+ }
+
+ return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
+ }
+```
+
+# [JavaScript](#tab/js3)
+
+```JavaScript
+class MainDailog {
+
+ this.addDialog(new OAuthPrompt(OAUTH_PROMPT, {
+ connectionName: process.env.connectionName,
+ text: 'Please Sign In',
+ Title: 'Sign In',
+ timeout: 300000
+ }));
+
+ this.addDialog(new ConfirmPrompt(CONFIRM_PROMPT));
+
+ this.addDialog(new WaterfallDialog(MAIN_WATERFALL_DIALOG, [
+ this.promptStep.bind(this),
+ this.loginStep.bind(this),
+ ]));
+
+ this.initialDialogId = MAIN_WATERFALL_DIALOG;
+
+ }
+
+async promptStep(stepContext) {
+ try {
+ return await stepContext.beginDialog(OAUTH_PROMPT);
+ } catch (err) {
+ console.error(err);
+ }
+ }
+
+async loginStep(stepContext) {
+ // Get the token from the previous step. Note that we could also have gotten the
+ // token directly from the prompt itself. There is an example of this in the next method.
+ const tokenResponse = stepContext.result;
+ if (!tokenResponse || !tokenResponse.token) {
+ await stepContext.context.sendActivity('Login was not successful please try again.');
+ } else {
+ const token = tokenResponse.token;
+ // On successful login, the token contains sign in token.
+ }
+ return await stepContext.endDialog();
+ }
+```
++
+> [!NOTE]
+> The code snippets use the Waterfall Dialog bot. For more information about Waterfall Dialog, see [About component and waterfall dialogs](/azure/bot-service/bot-builder-concept-waterfall-dialogs?view=azure-bot-service-4.0&preserve-view=true).
+
+You receive the token in `OnTeamsMessagingExtensionQueryAsync` handler in the `turnContext.Activity.Value` payload or in the `OnTeamsAppBasedLinkQueryAsync`, depending on which scenario you're enabling SSO for.
+
+```json
+JObject valueObject=JObject.FromObject(turnContext.Activity.Value);
+if(valueObject["authentication"] !=null)
+ {
+ JObject authenticationObject=JObject.FromObject(valueObject["authentication"]);
+ if(authenticationObject["token"] !=null)
+ }
+```
+
+### Validate the access token
+
+Web APIs on your server must decode the access token and verify if it's sent from the client.
+
+> [!NOTE]
+> If you use Bot Framework, it handles the access token validation. If you don't use Bot Framework, follow the guidelines in this section.
+
+For more information about validating access token, see [Validate tokens](/azure/active-directory/develop/access-tokens#validate-tokens).
+
+There are a number of libraries available that can handle JWT validation. Basic validation includes:
+
+- Checking that the token is well-formed.
+- Checking that the token was issued by the intended authority.
+- Checking that the token is targeted to the web API.
+
+Keep in mind the following guidelines when validating the token:
+
+- Valid SSO tokens are issued by Azure AD. The `iss` claim in the token should start with this value.
+- The token's `aud1` parameter will be set to the app ID generated during Azure AD app registration.
+- The token's `scp` parameter will be set to `access_as_user`.
+
+#### Example access token
+
+The following is a typical decoded payload of an access token.
+
+```javascript
+{
+ aud: "2c3caa80-93f9-425e-8b85-0745f50c0d24",
+ iss: "https://login.microsoftonline.com/fec4f964-8bc9-4fac-b972-1c1da35adbcd/v2.0",
+ iat: 1521143967,
+ nbf: 1521143967,
+ exp: 1521147867,
+ aio: "ATQAy/8GAAAA0agfnU4DTJUlEqGLisMtBk5q6z+6DB+sgiRjB/Ni73q83y0B86yBHU/WFJnlMQJ8",
+ azp: "e4590ed6-62b3-5102-beff-bad2292ab01c",
+ azpacr: "0",
+ e_exp: 262800,
+ name: "Mila Nikolova",
+ oid: "6467882c-fdfd-4354-a1ed-4e13f064be25",
+ preferred_username: "milan@contoso.com",
+ scp: "access_as_user",
+ sub: "XkjgWjdmaZ-_xDmhgN1BMP2vL2YOfeVxfPT_o8GRWaw",
+ tid: "fec4f964-8bc9-4fac-b972-1c1da35adbcd",
+ uti: "MICAQyhrH02ov54bCtIDAA",
+ ver: "2.0"
+}
+```
+
+## Add token to Bot Framework Token Store
+
+If you're using the OAuth connection, you must update or add the token in the Bot Framework Token store. Add the following code snippet example to `TeamsMessagingExtensionsSearchAuthConfigBot.cs` (or the equivalent file in your app's code) for updating or adding the token in the store:
+
+> [!NOTE]
+> You can find the sample `TeamsMessagingExtensionsSearchAuthConfigBot.cs` in [Tab, Bot, and Message Extension (ME) SSO](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-sso/csharp/App%20SSO%20Sample/Bots).
+
+```c#
+protected override async Task<InvokeResponse> OnInvokeActivityAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken)
+ {
+ JObject valueObject = JObject.FromObject(turnContext.Activity.Value);
+ if (valueObject["authentication"] != null)
+ {
+ JObject authenticationObject = JObject.FromObject(valueObject["authentication"]);
+ if (authenticationObject["token"] != null)
+ {
+ //If the token is NOT exchangeable, then return 412 to require user consent.
+ if (await TokenIsExchangeable(turnContext, cancellationToken))
+ {
+ return await base.OnInvokeActivityAsync(turnContext, cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ var response = new InvokeResponse();
+ response.Status = 412;
+ return response;
+ }
+ }
+ }
+ return await base.OnInvokeActivityAsync(turnContext, cancellationToken).ConfigureAwait(false);
+ }
+ private async Task<bool> TokenIsExchangeable(ITurnContext turnContext, CancellationToken cancellationToken)
+ {
+ TokenResponse tokenExchangeResponse = null;
+ try
+ {
+ JObject valueObject = JObject.FromObject(turnContext.Activity.Value);
+ var tokenExchangeRequest =
+ ((JObject)valueObject["authentication"])?.ToObject<TokenExchangeInvokeRequest>();
+ var userTokenClient = turnContext.TurnState.Get<UserTokenClient>();
+ tokenExchangeResponse = await userTokenClient.ExchangeTokenAsync(
+ turnContext.Activity.From.Id,
+ _connectionName,
+ turnContext.Activity.ChannelId,
+ new TokenExchangeRequest
+ {
+ Token = tokenExchangeRequest.Token,
+ },
+ cancellationToken).ConfigureAwait(false);
+ }
+ #pragma warning disable CA1031 //Do not catch general exception types (ignoring, see comment below)
+ catch
+ #pragma warning restore CA1031 //Do not catch general exception types
+ {
+ //ignore exceptions.
+ //if token exchange failed for any reason, tokenExchangeResponse above remains null, and a failure invoke response is sent to the caller.
+ //This ensures the caller knows that the invoke has failed.
+ }
+ if (tokenExchangeResponse == null || string.IsNullOrEmpty(tokenExchangeResponse.Token))
+ {
+ return false;
+ }
+ return true;
+ }
+```
+
+## Handle app user log out
+
+Use the following code snippet to handle the access token in case the app user logs out:
+
+# [csharp](#tab/cs4)
+
+```csharp
+ private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc,
+ CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (innerDc.Context.Activity.Type == ActivityTypes.Message)
+ {
+ var text = innerDc.Context.Activity.Text.ToLowerInvariant();
+
+ // Allow logout anywhere in the command.
+ if (text.IndexOf("logout") >= 0)
+ {
+ // The UserTokenClient encapsulates the authentication processes.
+ var userTokenClient = innerDc.Context.TurnState.Get<UserTokenClient>();
+ await userTokenClient.SignOutUserAsync(
+ innerDc.Context.Activity.From.Id,
+ ConnectionName,
+ innerDc.Context.Activity.ChannelId,
+ cancellationToken
+ ).ConfigureAwait(false);
+
+ await innerDc.Context.SendActivityAsync(MessageFactory.Text("You have been signed out."), cancellationToken);
+ return await innerDc.CancelAllDialogsAsync(cancellationToken);
+ }
+ }
+
+ return null;
+ }
+```
+
+# [JavaScript](#tab/js4)
+
+```JavaScript
+ async interrupt(innerDc) {
+ if (innerDc.context.activity.type === ActivityTypes.Message) {
+ const text = innerDc.context.activity.text.toLowerCase();
+ if (text === 'logout') {
+ const userTokenClient = innerDc.context.turnState.get(innerDc.context.adapter.UserTokenClientKey);
+
+ const { activity } = innerDc.context;
+ await userTokenClient.signOutUser(activity.from.id, this.connectionName, activity.channelId);
+
+ await innerDc.context.sendActivity('You have been signed out.');
+ return await innerDc.cancelAllDialogs();
+ }
+ }
+ }
+```
+++
+## Code sample
+
+This section provides bot authentication v3 SDK sample.
++
+| **Sample name** | **Description** | **C#** | **Node.js** | **Python** |
+||||-||
+| Bot authentication | This sample shows how to get started with authentication in a bot for Teams. | [View](https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/46.teams-auth) | [View](https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/javascript_nodejs/46.teams-auth) | [View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/python/46.teams-auth) |
+| Tab, bot, and Message extension (ME) SSO | This sample shows SSO for tab, bot, and message extension - search, action, link unfurl. | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-sso/csharp) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-sso/nodejs) | NA |
+|Tab, bot, and Message extension | This sample shows how to check authentication in bot, tab, and message extension with SSO | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-complete-auth/csharp) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-complete-auth/nodejs) | NA |
platform Add Authentication https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/messaging-extensions/how-to/add-authentication.md
Title: Add authentication to your message extension
+ Title: Add third party authentication to your message extension
-description: Enable authentication in Teams message extension app using third-party OAuth provider with Azure AD configuration and code sample.
+description: Enable authentication in Teams message extension app using third-party provider with Azure AD configuration and code sample.
ms.localizationpriority: medium
-# Add authentication to your message extension
+# Add third party authentication to your message extension
[!include[v4-to-v3-SDK-pointer](~/includes/v4-to-v3-pointer-me.md)] > [!NOTE]
-> After adding authentication to the message extension, the user must add "**token.botframework.com**" to the "**validDomains**" section in the manifest.
+> After adding authentication to the message extension, you must add "**token.botframework.com**" to the "**validDomains**" section in the manifest.
## Identify the user
The sequence is as follows:
1. After the user signs in, you should close your window and send an **authentication code** to the Teams client. 1. The Teams client then reissues the query to your service, which includes the authentication code passed in Step 5.
-Your service should verify that the authentication code received in step 6 matches with step 5. The steps ensure that a malicious user doesn't try to spoof or compromise the sign in flow. The flow effectively "closes the loop" to finish the secure authentication sequence.
+Your service should verify the authentication code received in step 6 matches with step 5. The steps ensure that a malicious user doesn't try to spoof or compromise the sign-in flow. The flow effectively "closes the loop" to finish the secure authentication sequence.
### Respond with a sign in action
At this point, the window closes and the control is passed to the Teams client.
## See also
-[Single sign-on (SSO) support for message extensions](~/messaging-extensions/how-to/enable-sso-auth-me.md)
+[Enable SSO for your bot and message extension app](../../bots/how-to/authentication/bot-sso-overview.md)
platform Enable SSO Auth Me https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/messaging-extensions/how-to/enable-SSO-auth-me.md
- Title: SSO support for your message extensions-
-description: Enable Single sign-on (SSO) in your Teams message extension app using Azure AD and code sample.
----
-# Enable SSO for message extensions
-
-Single sign-on (SSO) support is now available for message extensions and link unfurling. Enabling Single sign-on for message extensions by default refreshes the authentication token, which minimizes the number of times you need to enter the sign in credentials for Microsoft Teams.
-
-This document guides you on how to enable the SSO and store your authentication token, if necessary.
-
-## Prerequisites
-
-The prerequisite to enable SSO for message extensions and link unfurling are as follows:
-
-* You must have an [Azure](https://azure.microsoft.com/free/) account.
-* You must Configure your app through the Azure AD portal, and update Teams application manifest your bot as defined in [register your app through the Azure AD portal](../../bots/how-to/authentication/auth-aad-sso-bots.md#register-your-app-through-the-azure-ad-portal).
-
-> [!NOTE]
-> For more information on creating an Azure account and updating your app manifest, see [Single sign-on (SSO) support for bots](../../bots/how-to/authentication/auth-aad-sso-bots.md).
-
-## Enable SSO for message extensions and link unfurling
-
-After the prerequisites are completed, you can enable SSO for message extensions and link unfurling.
-
-To enable SSO:
-
-1. Update your bots [OAuth connection](../../bots/how-to/authentication/auth-aad-sso-bots.md#update-the-azure-portal-with-the-oauth-connection) details in the Microsoft Azure portal.
-2. Download the [message extensions sample](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/52.teams-messaging-extensions-search-auth-config) and follow the setup instructions provided by the wizard.
- > [!NOTE]
- > Use your bots OAuth connection when setting up your message extensions.
-3. In the [TeamsMessagingExtensionsSearchAuthConfigBot.cs](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/52.teams-messaging-extensions-search-auth-config/Bots/TeamsMessagingExtensionsSearchAuthConfigBot.cs) file, update the value from *auth* to *silentAuth* in the `OnTeamsMessagingExtensionQueryAsync` and / or `OnTeamsAppBasedLinkQueryAsync`.
-
- > [!NOTE]
- > We do not support other handlers SSO, except `OnTeamsMessagingExtensionQueryAsync` and `OnTeamsAppBasedLinkQueryAsync` from the TeamsMessagingExtensionsSearchAuthConfigBot.cs file.
-
-4. You receive the token in `OnTeamsMessagingExtensionQueryAsync` handler in the `turnContext.Activity.Value` payload or in the `OnTeamsAppBasedLinkQueryAsync`, depending on which scenario you're enabling the SSO for:
-
- ```json
- JObject valueObject=JObject.FromObject(turnContext.Activity.Value);
- if(valueObject["authentication"] !=null)
- {
- JObject authenticationObject=JObject.FromObject(valueObject["authentication"]);
- if(authenticationObject["token"] !=null)
- }
-
- ```
-
- If you're using the OAuth connection, add the following code to the TeamsMessagingExtensionsSearchAuthConfigBot.cs file to update or add the token in the store:
-
- ```C#
- protected override async Task<InvokeResponse> OnInvokeActivityAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken)
- {
- JObject valueObject = JObject.FromObject(turnContext.Activity.Value);
- if (valueObject["authentication"] != null)
- {
- JObject authenticationObject = JObject.FromObject(valueObject["authentication"]);
- if (authenticationObject["token"] != null)
- {
- //If the token is NOT exchangeable, then return 412 to require user consent
- if (await TokenIsExchangeable(turnContext, cancellationToken))
- {
- return await base.OnInvokeActivityAsync(turnContext, cancellationToken).ConfigureAwait(false);
- }
- else
- {
- var response = new InvokeResponse();
- response.Status = 412;
- return response;
- }
- }
- }
- return await base.OnInvokeActivityAsync(turnContext, cancellationToken).ConfigureAwait(false);
- }
- private async Task<bool> TokenIsExchangeable(ITurnContext turnContext, CancellationToken cancellationToken)
- {
- TokenResponse tokenExchangeResponse = null;
- try
- {
- JObject valueObject = JObject.FromObject(turnContext.Activity.Value);
- var tokenExchangeRequest =
- ((JObject)valueObject["authentication"])?.ToObject<TokenExchangeInvokeRequest>();
- var userTokenClient = turnContext.TurnState.Get<UserTokenClient>();
- tokenExchangeResponse = await userTokenClient.ExchangeTokenAsync(
- turnContext.Activity.From.Id,
- _connectionName,
- turnContext.Activity.ChannelId,
- new TokenExchangeRequest
- {
- Token = tokenExchangeRequest.Token,
- },
- cancellationToken).ConfigureAwait(false);
- }
- #pragma warning disable CA1031 //Do not catch general exception types (ignoring, see comment below)
- catch
- #pragma warning restore CA1031 //Do not catch general exception types
- {
- //ignore exceptions
- //if token exchange failed for any reason, tokenExchangeResponse above remains null, and a failure invoke response is sent to the caller.
- //This ensures the caller knows that the invoke has failed.
- }
- if (tokenExchangeResponse == null || string.IsNullOrEmpty(tokenExchangeResponse.Token))
- {
- return false;
- }
- return true;
- }
-
- ```
-
-## Code sample
-
-This section provides Bot authentication v3 SDK sample.
-
-| **Sample name** | **Description** | **.NET** | **Node.js** | **Python** |
-||||-||
-| Bot authentication | This sample shows how to get started with authentication in a bot for Teams. | [View](https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/46.teams-auth) | [View](https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/javascript_nodejs/46.teams-auth) | [View](https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/python/46.teams-auth) |
-| Tab, Bot and Message Extension (ME) SSO | This sample shows SSO for Tab, Bot and ME - search, action, link unfurl. | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-sso/csharp) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-sso/nodejs) | NA |
-|Tab, Bot, and Message extension| This sample shows how to check authentication in Bot,Tab, and Message extension with SSO | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-complete-auth/csharp) | [View](https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-complete-auth/nodejs) | NA |
-
-## See also
-
-* [Add authentication to your message extensions](add-authentication.md)
-* [Use SSO for bots](../../bots/how-to/authentication/auth-aad-sso-bots.md)
-* [Link unfurling](link-unfurling.md)
platform Tab Sso Graph Api https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/authentication/tab-sso-graph-api.md
ms.localizationpriority: high keywords: teams authentication tabs Microsoft Azure Active Directory (Azure AD) Graph API Delegated permission access token scope
-# Extend tab app with Microsoft Graph permissions and scope
+# Extend tab app with Microsoft Graph permissions and scopes
You can extend your tab app by using Microsoft Graph to allow users additional permissions, such as to view app user profile, to read mail, and more. Your app must ask for specific permission scopes to obtain the access tokens on app user's consent.
You can configure additional Graph scopes in Azure AD for your app. These are de
1. Open the app you registered in the [Azure portal](https://ms.portal.azure.com/).
-2. Select **Manage** > **API permission** from the left pane.
+2. Select **Manage** > **API permissions** from the left pane.
:::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/api-permission-menu.png" alt-text="App permissions menu option."::: The **API permissions** page appears.
-3. Select **+ Add permissions** to add Microsoft Graph API permissions.
+3. Select **+ Add a permission** to add Microsoft Graph API permissions.
:::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/app-permission.png" alt-text="App permissions page.":::
platform Tab Sso Manifest https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/authentication/tab-sso-manifest.md
keywords: teams authentication tabs Microsoft Azure Active Directory (Azure AD)
# Update manifest for SSO and preview app
-Before you update Teams app manifest, ensure that you've configure code to enable SSO in your tab app.
+Before you update Teams app manifest, ensure that you've configured code to enable SSO in your tab app.
> [!div class="nextstepaction"] > [Configure code](tab-sso-code.md)
For more information, see [webApplicationInfo](../../../resources/schema/manifes
1. Open the tab app project. 2. Open the manifest folder.
- > [!NOTE]
- >
- > - The manifest folder should be at the root of your project. For more information, see [Create a Microsoft Teams app package](../../../concepts/build-and-test/apps-package.md).
- > - For more information on learning how to create a manifest.json, see [Reference: Manifest schema for Microsoft Teams](../../../resources/schem).
+ > [!NOTE]
+ >
+ > - The manifest folder should be at the root of your project. For more information, see [Create a Microsoft Teams app package](../../../concepts/build-and-test/apps-package.md).
+ > - For more information on learning how to create a manifest.json, see [Reference: Manifest schema for Microsoft Teams](../../../resources/schem).
-1. Open the manifest.json file
+1. Open the `manifest.json` file
1. Append the following code snippet to the manifest file to add the new property: ```json
For more information, see [webApplicationInfo](../../../resources/schema/manifes
</details> > [!NOTE]
-> During debug, you can use ngrok to test your app in Azure AD. In that case, you need to replace the subdomain in `api://subdomain.example.com/00000000-0000-0000-0000-000000000000` with the ngrok url. You'll need to update the url whenever your ngrok subdomain changes For example, api://23c3-103-50-148-128.ngrok.io/bccfbe67-e08b-4ec1-a7fd-e0aaf41a097c.
+> During debug, you can use ngrok to test your app in Azure AD. In that case, you need to replace the subdomain in `api://subdomain.example.com/00000000-0000-0000-0000-000000000000` with the ngrok URL. You'll need to update the URL whenever your ngrok subdomain changes. For example, api://23c3-103-50-148-128.ngrok.io/bccfbe67-e08b-4ec1-a7fd-e0aaf41a097c.
## Sideload and Preview in Teams
platform Tab Sso Overview https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/authentication/tab-sso-overview.md
Title: Overview to authentication for tabs using SSO in Teams with Azure AD
description: Learn about Single sign-on (SSO) authentication in Teams and how to enable it in tabs. ms.localizationpriority: high
-keywords: teams authentication tabs Microsoft Azure Active Directory (Azure AD) SSO access token app manifest
# Enable SSO for tab app
-<!--Single sign-on (SSO) allows a user to access an application or a web service after signing-in only once. The app users never have to go through authentication again.-->
-
-With SSO in Teams, app users have the advantage of using Teams to access apps. After logging into Teams using Microsoft or Microsoft 365 account, app users can use your app without needing to sign in again. Your app is available to app users on any device with access granted through Azure AD.
+With SSO in Teams, app users have the advantage of using Teams to access tab apps. After logging into Teams using Microsoft or Microsoft 365 account, app users can use your app without needing to sign in again. Your app is available to app users on any device with access granted through Azure AD.
Here's what you'll learn in this section:
The following image shows how SSO works when a Teams app user attempts to access
| 5 | Teams Client → Tab app client | Teams sends the access token to the tab app as part of the result object returned by the `getAuthToken()` call. | | 6 | Tab app (between client & server) | The tab app parses the access token using JavaScript to extract required information, such as the app user's email address. The token returned to the tab app is both an access token and an identity token. |
-For more information, see [Update code to enable SSO](tab-sso-code.md).
+For more information, see [Add code to enable SSO in a tab app](tab-sso-code.md) and [Add code to enable SSO in your bot app](../../../bots/how-to/authentication/bot-sso-code.md).
> [!IMPORTANT] > The `getAuthToken()` is valid only for consenting to a limited set of user-level APIs, such as email, profile, offline_access, and OpenId. It isn't used for other Graph scopes such as `User.Read` or `Mail.Read`. For suggested workarounds, see [Extend your app with Microsoft Graph permissions](tab-sso-graph-api.md).
Some scenarios where you can use the SSO API to authenticate your app users are:
To achieve SSO at runtime, configure your app to enable SSO for authenticating and authorizing app users.
-## Enable SSO for a tab app
+## Enable SSO for a Teams tab app
-This section describes the tasks involved in implementing SSO for a tab app. These tasks are language- and framework-agnostic.
+This section describes the tasks involved in implementing SSO for a Teams app. These tasks are language- and framework-agnostic.
-To enable SSO for a tab app:
+To enable SSO for a Teams tab app:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/enable-sso.png" alt-text="Steps to enable SSO for tab" lightbox="../../../assets/images/authentication/teams-sso-tabs/enable-sso.png":::
-1. **Register with Azure AD**: Create an Azure AD app to generate an app ID and application ID URI. For generating access token, you configure scopes and authorize trusted client applications.
-2. **Update code**: Add the code to handle access token, calling `getAuthToken()` when an app user accesses your tab app, sending this token to your app's server code in the Authorization header, and validating the access token when it's received.
+1. **Configure app with Azure AD**: Create an Azure AD app to generate an app ID and application ID URI. For generating access token, you configure scopes and authorize trusted client applications.
+2. **Add code**: Add the code to handle access token, sending this token to your app's server code in the Authorization header, and validating the access token when it's received.
3. **Update Teams app manifest**: Update your Teams Client app manifest with the app ID and application ID URI generated on Azure AD to allow Teams to request access tokens on behalf of your app. ## Third-party cookies on iOS
For Teams mobile, client versions that support SSO are:
For the best experience with Teams, use the latest version of iOS and Android.
+## Step-by-step guides
+
+Use the following step-by-step guides for enabling SSO for Teams app:
+
+- [AAD SSO for tabs and message extension](../../../sbs-tabs-and-messaging-extensions-with-sso.yml)
+- [Build a bot with SSO authentication](../../../sbs-bots-with-sso.yml)
+ ## Best practices Here's a list of best practices:
Here's a list of best practices:
## Known limitations - Currently, SSO in Teams supports only OAuth 2.0 token. It doesn't support SAML token.-- Multiple domains per app are not supported. For more information, see [LOB apps](tab-sso-register-aad.md#before-you-register-with-azure-ad).
+- Multiple domains per app are not supported. For more information, see [LOB apps](tab-sso-register-aad.md#before-you-configure-your-app).
## Next step
Here's a list of best practices:
## See also [Configure code to enable SSO in a tab app](tab-sso-code.md)-
-<!--
-### Use cases for enabling SSO for tab app
-
-Here are some use cases where enabling SSO is beneficial. Call `getAuthToken()` in these scenarios to use Teams identity for obtaining access token for your app users:
--- To get an app userΓÇÖs identity from Teams if you have an existing app that you want to be available within a tab app in Teams.--- To authenticate an app user by reusing the TeamΓÇÖs identity inside your tab app.--- To authenticate and get an app userΓÇÖs Teams identity inside configurable tabs. The app users don't need to sign in again. It's applicable to some settings that need to be configured at a configuration stage.--- To obtain an access token inside a task module, when it's invoked from a tab app, a bot app, a messaging extension app, or adaptive cards.--- To authenticate an app user in Stage view.--- To authenticate users for [task modules](../../../task-modules-and-cards/what-are-task-modules.md) that embed web content.>-
-<!--
-```mermaid
-sequenceDiagram
- User->>Tab app: Opens Teams app
- Tab app->>Teams Client: 1. Call getAuthToken()
- Teams Client->>Sign-in and Consent: 2. Check if consent is required
- Sign-in and Consent->>Teams Client: Prompt for consent from new user
- Teams Client->>Azure AD: 3. Request access token from Azure AD
- Azure AD->>Teams Client: 4. Send access token to Teams Client
- Teams Client->>Tab app: 5. Respond to getAuthToken() with access token
- Tab app->>Tab app: 6. Parse access token to give access to user
-```
>-
-<!--
-- Tenant admin consent: A simple way of [consenting on behalf of an organization as a tenant admin](/azure/active-directory/develop/v2-permissions-and-consent.md#requesting-consent-for-an-entire-tenant) is by getting [consent from admin](/azure/active-directory/manage-apps/grant-admin-consent).
-
- You can ask for consent using the Auth API. Another approach for getting Graph scopes is to present a consent dialog using our existing [third party OAuth provider authentication approach](~/tabs/how-to/authentication/auth-tab-aad.md#navigate-to-the-authorization-page-from-your-pop-up-page). This approach involves popping up an Azure AD consent dialog box.
-
- <details>
- <summary>To ask for additional consent using the Auth API, follow these steps:</summary>
-
- 1. The token retrieved using `getAuthToken()` must be exchanged on the server-side using Azure AD [on-behalf-of flow (OBO)](/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow) to get access to those other Graph APIs. Ensure you use the v2 Graph endpoint for this exchange.
- 2. If the exchange fails, Azure AD returns an invalid grant exception. It usually responds with one of the two error messages, `invalid_grant` or `interaction_required`.
- 3. When the exchange fails, you must ask for consent. Use the user interface (UI) to ask the app user to grant other consent. This UI must include a button that triggers an Azure AD consent dialog using [Silent authentication](~/concepts/authentication/auth-silent-aad.md).
- 4. When asking for more consent from Azure AD, you must include `prompt=consent` in your [query-string-parameter](~/tabs/how-to/authentication/auth-silent-aad.md#get-the-user-context) to Azure AD, otherwise Azure AD wouldn't ask for other scopes.
-
- - Instead of `?scope={scopes}`, use `?prompt=consent&scope={scopes}`
- - Ensure that `{scopes}` includes all the scopes you're prompting the user for, for example, `Mail.Read` or `User.Read`.
- 5. After the app user has granted more permissions, retry the OBO flow to get access to these other APIs.
-
- </details>
>
-<!--
-- If you want your existing app to be available within a Teams tab app, the SSO API allows your signed-in app users to use your app in Teams with no additional authentication needed. Based on the app user's Teams identity, you can obtain access token for them from Azure AD.-- If your app has configurable tabs, you can use `getAuthToken()` to allow app users into the tab app without signing in again. SSO is applicable to some settings that need to be configured at a configuration stage.-- Your app may have a bot, a tab, a message extension, or Adaptive Cards, and allows your app users to invoke task module from within a tab or a bot. The SSO API will authenticate your app users who attempt to access the task module. Teams can use the app user's Teams identity and obtain an access token from Azure AD.--- You can also use the SSO API for authenticating your app users who want to access to Stage view without need to be validated again. The access token obtained for the app user when they first used your app can be used to allow them to use Stage view. -->
platform Tab Sso Register Aad https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/authentication/tab-sso-register-aad.md
ms.localizationpriority: high keywords: teams authentication tabs Microsoft Azure Active Directory (Azure AD) access token SSO tenancy scope
-# Register your tab app in Azure AD
+# Configure your tab app in Azure AD
Azure AD provides access to your tab app based on the app user's Teams identity. You'll need to register your tab app with Azure AD so that the app user who has signed into Teams can be given access to your tab app.
-## Enabling SSO on Azure AD
+## Enabling SSO in Azure AD
-Registering your tab app in Azure AD and enabling it for SSO requires making app configurations, such as generating app ID, defining API scope, and pre-authorize client IDs for trusted applications.
+Register your tab app in Azure AD and enable it for SSO requires making app configurations, such as generating app ID, defining API scope, and pre-authorize client IDs for trusted applications.
:::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/register-azure-ad.png" alt-text="Configure Azure AD to send access token to Teams Client app":::
User-level Graph API permissions are supported, that is, email, profile, offline
Azure AD configuration enables SSO for your tab app in Teams. It responds with an access token for validating the app user.
-> [!NOTE]
-> Microsoft Teams Toolkit registers the Azure AD application in an SSO project.
-
-### Before you register with Azure AD
+### Before you configure your app
It's helpful if you learn about the configuration for registering your app on Azure AD beforehand. Ensure that you've prepared to configure the following details prior to registering your app: - **Single- or multi-tenant options**: Will your application be used in only the Microsoft 365 tenant where it's registered, or will many Microsoft 365 tenants use it? Applications written for one enterprise are typically single-tenant. Applications written by an independent software vendor and used by many customers need to be multi-tenant so each customer's tenant can access the application.-- **Application ID URI**: It's a globally unique URI that identifies the web API you expose for your app's access through scopes. It's also referred to as an identifier URI. The application ID URI includes the app ID and the subdomain where your app is hosted. Your application's domain name and the domain name you register for your Azure AD application should be the same. Currently, multiple domains per app aren't supported.
+- **Application ID URI**: It's a globally unique URI that identifies the web API you expose for your app's access through scopes. It's also referred to as an identifier URI. The application ID URI includes the app ID and the subdomain where your app is hosted. Your application's domain name and the domain name you register for your Azure AD application must be the same. Currently, multiple domains per app aren't supported.
- **Scope**: It's the permission that an authorized app user or your app can be granted for accessing a resource exposed by the API. > [!NOTE]
It's helpful if you learn about the configuration for registering your app on Az
To create and configure your app in Azure AD for enabling SSO: -- [Register and configure the Azure AD app.](#create-an-app-registration-in-azure-ad) - [Configure scope for access token.](#configure-scope-for-access-token) - [Configure access token version.](#configure-access-token-version)
-## Create an app registration in Azure AD
+## Configure your app in Azure AD
+
+You can configure your tab app in Azure AD to configure the scope and permissions for access tokens.
+
+You'll need to register your app in Azure AD and configure the tenancy and app's platform, before you can enable it for SSO. Azure AD generates a new app ID that you must note. You'll need to update it later in the Teams app manifest file.
-Register a new app in Azure AD, and configure the tenancy and app's platform. You'll generate a new app ID that will be updated later in your Teams app manifest file.
+> [!NOTE]
+> Microsoft Teams Toolkit registers the Azure AD application in an SSO project. You can skip this section if you've used Teams Toolkit to create your app. However, you would need to configure permissions and scope, and trust client applications.
+
+<details>
+<summary><b>Learn how to register your app in Azure AD</b></summary>
### To register a new app in Azure AD
Register a new app in Azure AD, and configure the tenancy and app's platform. Yo
8. Note and save the app ID from **Application (client) ID**. You'll need it for updating the Teams app manifest later.
- Your app is registered in Azure AD. You should now have app ID for your tab app.
+ Your app is registered in Azure AD. You now have app ID for your tab app.
-## Configure scope for access token
+</details>
+
+### Configure scope for access token
After you've created a new app registration, configure scope (permission) options for sending access token to Teams Client, and authorizing trusted client applications to enable SSO.
To configure scope and authorize trusted client applications, you'll need:
- [To configure API scope](#to-configure-api-scope): Define scope for the API, and the users who can consent for a scope. You can let only admins provide consent for higher-privileged permissions. - [To configure authorized client application](#to-configure-authorized-client-application): Create authorized client IDs for applications that you want to pre-authorize. It allows the app user to access the app scopes (permissions) you've configured, without requiring any further consent. Pre-authorize only those client applications you trust as your app users won't have the opportunity to decline consent.
-### To expose an API
+#### To expose an API
1. Select **Manage** > **Expose an API** from the left pane.
To configure scope and authorize trusted client applications, you'll need:
:::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/set-app-id-uri.png" alt-text="Application ID URI"::: - The **Application ID URI** is pre-filled with app ID (GUID) in the format `api://{AppID}`.
- - The application ID URI format should be: `api://fully-qualified-domain-name.com/{AppID}`.
+ - The application ID URI format must be: `api://fully-qualified-domain-name.com/{AppID}`.
- Insert the `fully-qualified-domain-name.com` between `api://` and `{AppID}` (which is, GUID). For example, api://example.com/{AppID}. where,
- - `fully-qualified-domain-name.com` is the human-readable domain name from which your tab app is served. Your application's domain name and the domain name you register for your Azure AD application should be the same.
+ - `fully-qualified-domain-name.com` is the human-readable domain name from which your tab app is served. Your application's domain name and the domain name you register for your Azure AD application must be the same.
If you're using a tunneling service, such as ngrok, you must update this value whenever your ngrok subdomain changes. - `AppID` is the app ID (GUID) that was generated when you registered your app. You can view it in the **Overview** section.
To configure scope and authorize trusted client applications, you'll need:
1. Note and save the Application ID URI. You'll need it for updating the Teams app manifest later.
-### To configure API scope
+#### To configure API scope
1. Select **+ Add a scope** in the **Scopes defined by this API** section.
To configure scope and authorize trusted client applications, you'll need:
:::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/scope-added.png" alt-text="Scope added and displayed":::
-### To configure authorized client application
+#### To configure authorized client application
1. Move through the **Expose an API** page to the **Authorized client application** section, and select **+ Add a client application**.
To configure scope and authorize trusted client applications, you'll need:
The **Add a client application** page appears.
-1. Enter the appropriate Microsoft 365 client ID for the Teams Client for the applications that you want to authorize for your appΓÇÖs web application.
+1. Enter the appropriate Microsoft 365 client ID for the applications that you want to authorize for your appΓÇÖs web application.
:::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/add-client-app.png" alt-text="Add a client application"::: > [!NOTE] >
- > - The Microsoft 365 client IDs for mobile, desktop, and web applications for Teams, Office, and Outlook are the actual IDs that you should add.
+ > - The Microsoft 365 client IDs for mobile, desktop, and web applications for Teams, Office, and Outlook are the actual IDs that you must add.
> - For a Teams tab app, you'll need either Web or SPA, as you can't have a mobile or desktop client application in Teams. 1. Choose one of the following client IDs:
To configure scope and authorize trusted client applications, you'll need:
:::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/update-app-auth-msg.png" alt-text="Client application added message":::
- The client ID displays on the page.
+ The authorized app's client ID displays on the page.
:::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/client-app-added.png" alt-text="Client app added and displayed"::: > [!NOTE] > You can authorize more than one client application. Repeat the steps of this procedure for configuring another authorized client application.
-## Configure access token version
+You've successfully configured app scope, permissions, and client applications. Ensure that you note and save the application ID URI. Next, you configure the access token version.
+
+### Configure access token version
-You must define the access token version that is acceptable for your app. This configuration is made in the Azure AD application manifest.
+You must define the access token version for your app. This configuration is made in the Azure AD application manifest.
-### To define the access token version
+#### To define the access token version
1. Select **Manage** > **Manifest** from the left pane.
platform Tab Sso Troubleshooting https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/authentication/tab-sso-troubleshooting.md
For more information, see [Graph explorer](https://developer.microsoft.com/graph
<details> <summary>1. Error: consent missing.</summary> <br>
-When Azure AD receives a request for accessing a Microsoft Graph resource, it checks if the user (or tenant administrator) have given consent for this resource. If there's no record of consent from the user or administrator, Azure AD sends an error message to your web service.
+When Azure AD receives a request for accessing a Microsoft Graph resource, it checks if the app user or tenant administrator has given consent for this resource. If there's no record of consent from the user or administrator, Azure AD sends an error message to your web service.
Your code must tell the client (for example, in the body of a 403 Forbidden response) how to handle the error:
To handle this error, your server-side code should send a 403 Forbidden resp
<details> <summary>3. Error: Invalid Audience in the access token for Microsoft Graph.</summary> <br>
-The server-side code should send a 403 Forbidden response to the client to show a message to the user. It is recommended that it should also log the error to the console, or record it in a log.
+The server-side code should send a 403 Forbidden response to the client to show a message to the user. It's recommended that it should also log the error to the console, or record it in a log.
</details> <br> <details>
The server-side code should send a 403 Forbidden response to the client to s
<br> You can get this error in one of the two scenarios:
-1. The custom domain is not added to Azure AD. To add custom domain to Azure AD and register it, follow the [add a custom domain name to Azure AD](/azure/active-directory/fundamentals/add-custom-domain) procedure, and then follow the steps to [Configure scope for access token](tab-sso-register-aad.md#configure-scope-for-access-token) again.
-1. You are not signed in with Administrator credentials in the Microsoft 365 tenancy. Sign-in to Microsoft 365 as an administrator.
+1. The custom domain isn't added to Azure AD. To add custom domain to Azure AD and register it, follow the [add a custom domain name to Azure AD](/azure/active-directory/fundamentals/add-custom-domain) procedure. Then follow the steps to [Configure scope for access token](tab-sso-register-aad.md#configure-scope-for-access-token) again.
+1. You aren't signed in with Administrator credentials in the Microsoft 365 tenancy. Sign-in to Microsoft 365 as an administrator.
</details> <br>
Check that the following values match between Azure AD, client-side code, and Te
- **Application ID URI**: The app ID URI in the code and in Teams app manifest file should match the **Application ID URI** in Azure AD. -- **App permissions**: Check if the permissions you defined in the scope are as per your app requirement. If so, check if they were granted to the user in the access token.
+- **App permissions**: Check if the permissions you defined in the scope are as per your app requirement. If so, check if they had been granted to the user in the access token.
- **Admin consent**: If any scope requires admin consent, check if the consent was granted for the particular scope to the user.
In addition, inspect the access token that was sent to the tab app to verify if
- **Audience (aud)**: Check if the app ID in the token is correct as given in Azure AD. - **Tenant Id(tid)**: Check if the tenant mentioned in the token is correct.-- **User identity (preferred_username)**: Check if the user identity matches the username in the request for access token for the scope that the current user wants to access.
+- **User identity (preferred_username)**: Check if the user identity matches the username in the request for access token, for the scope that the current user wants to access.
- **Scopes (scp)**: Check if the scope for which the access token is requested is correct, and as defined in Azure AD. - **Azure AD version 1.0 or 2.0 (ver)**: Check if Azure AD version is correct. You can use [JWT](https://jwt.ms) for inspecting the token. </details>+
+## Bot SSO token error
+<br>
+<details>
+<summary>Token exchange failure.</summary>
+<br>
+If there's a token exchange failure, use the following code:
+
+```json
+{ΓÇïΓÇï
+ "status": "<response code>",
+ "body":
+ {ΓÇïΓÇï
+ "id":"<unique Id>",
+ "connectionName": "<connection Name on the bot (from the OAuth card)>",
+ "failureDetail": "<failure reason if status code is not 200, null otherwise>"
+ }ΓÇïΓÇï
+}ΓÇïΓÇï
+```
+
+To understand the bot behavior when the token exchange fails to trigger a consent prompt, see the following steps:
+
+>[!NOTE]
+> No user action is required to be taken as the bot takes the actions when the token exchange fails.
+
+1. The client starts a conversation with the bot triggering an OAuth scenario.
+2. The bot sends back an OAuth card to the client.
+3. The client intercepts the OAuth card before displaying it to the app user. It checks if it contains a `TokenExchangeResource` property.
+4. If the property exists, the client sends a `TokenExchangeInvokeRequest` to the bot. The client must have an exchangeable token for the user. This token must be an Azure AD v2 token whose audience must be the same as `TokenExchangeResource.Uri` property.
+1. The client sends an invoke activity to the bot with the following code:
+
+ ```json
+ {
+ "type": "Invoke",
+ "name": "signin/tokenExchange",
+ "value":
+ {
+ "id": "<any unique Id>",
+ "connectionName": "<connection Name on the skill bot (from the OAuth card)>",
+ "token": "<exchangeable token>"
+ }
+ }
+ ```
+
+5. The bot processes the `TokenExchangeInvokeRequest` and returns a `TokenExchangeInvokeResponse` back to the client. The client must wait until it receives the `TokenExchangeInvokeResponse`.
+
+ ```json
+ {
+ "status": "<response code>",
+ "body":
+ {
+ "id":"<unique Id>",
+ "connectionName": "<connection Name on the skill bot (from the OAuth card)>",
+ "failureDetail": "<failure reason if status code is not 200, null otherwise>"
+ }
+ }
+ ```
+
+6. If the `TokenExchangeInvokeResponse` has a `status` of `200`, then the client doesn't show the OAuth card. See the [normal flow image](/azure/bot-service/bot-builder-concept-sso?view=azure-bot-service-4.0#sso-components-interaction&preserve-view=true). For any other `status` or if the `TokenExchangeInvokeResponse` isn't received, then the client shows the OAuth card to the user. See the [fallback flow image](/azure/bot-service/bot-builder-concept-sso?view=azure-bot-service-4.0#sso-components-interaction&preserve-view=true). If there are any errors or unmet dependencies like user consent, this activity ensures that the SSO flow falls back to normal OAuthCard flow.
+
+</details>
platform Whats New https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/whats-new.md
Teams platform features that are available to all app developers.
**2022 November**
+* ***November 22, 2022***: [Enable SSO for your bot and message extension app](bots/how-to/authentication/bot-sso-overview.md).
+ * ***November 18, 2022***: [Zero install for link unfurling](messaging-extensions/how-to/link-unfurling.md#zero-install-for-link-unfurling). * ***November 17, 2022***: [Manifest schema v1.5](resources/schem).