microsoft / botframework-sdk

Bot Framework provides the most comprehensive experience for building conversation applications.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

UserAssignedMSI + AzureADMyOrg + Teams = Seamless SSO does not work.

stas-sultanov opened this issue · comments

Version

Version="4.21.0"

Describe the bug

We create a Teams Chat Bot for internal use in our organization.
In EntraID Application Registration we specify "SignInAudience": "AzureADMyOrg".
We use User Assigned Managed Service identity for Azure Bot Service.
In bot application we specify "MicrosoftAppType": "UserAssignedMSI".

In this configuration seamless SSO does not work.
During SingIn Teams shows us a Sign-In card instead of consent.
We are able to sign-in and bot works.
This happens because in Azure Bot Service Connection AADv2 Token Exchange Url we specify nothing.
And bot application sends OAuthCard with empty TokenExchangeResource.

If only we specify Token Exchange Url in Azure Bot Service Connection AADv2 we see it in
OAuthCard.TokenExchangeResource.
With such configuration bot service stop respond.

There are a lot of documents saying that Azure Bot Service Connection AADv2 Token Exchange Url should be blank but this value is need by Teams to Exchange Token.

Thanks @stas-sultanov, i'm looking into this.

Hi @stas-sultanov,

  1. Are you facing this issue in production or development?
  2. Are you following a specific documentation to implement SSO for user assigned managed identity? if yes, could you please share that documentation link?

I can try to setup an SSO bot with user assigned managed identity to see if I can reproduce this issue.

Typically in the past, when I implemented SSO for MultiTenant app type, the Token Exchange URL is indeed required.
https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/bot-conversation-sso-quickstart/BotSSOSetup.md#3-setup-bot-service-connection-tokenstore:~:text=For%20the%20Token%20Exchange%20URL%20use%20the%20Application%20ID%20URL%20obtained%20in%20step%201.3

image

hi @ramfattah, thank you for your time.

  1. we can not move to production because we are facing issue in DEVelopment.
  2. we do not follow one documentation, because there is no such.
    We can not find reliable end-to-end documentation that explains how to setup a Teams Bot with following combined:
    • Single Tenant App Registration in EntraID
    • Managed Service Identity for Azure Bot Service
    • SSO

There are documents that tells how to use Managed Service Identity for Azure Bot Service, like this one but nothing about Teams Single Tenant App with SSO

There are documents like the one you have mentioned, but they are about Teams with SSO that uses Multitenant App Registration in EntraID and no Managed Service Identity for Azure Bot Service.

Also there is a document, that just mentions following
"MicrosoftAppType" in the appsettings.json. (Allowed values are: MultiTenant(default), SingleTenant, UserAssignedMSI)
but no details

Hi @stas-sultanov,

Could you please provide detailed steps to reproduce the issue?

Specifically, how you created the app registration, information provided to OAuth identity service provider and when interacting with the bot.

Thanks.

Hi @ramfattah
there is a lot of information, this is why I'll split it to several posts.

Part 1
we utilize Azure DevOps pipeline to automatically create EntraID App Registration with help of Powershell MS Graph
here is a sample of app registration manifest (default values are omitted)

Please note:

  1. We specify "SignInAudience": "AzureADMyOrg", because we build Single Tenant solution.
{
	"AccessTokenAcceptedVersion": 2,
	"Api":
	{
		"Oauth2PermissionScopes":
		[
			{
				"AdminConsentDescription": "Allow application to interact with other systems on behalf of the current user.",
				"AdminConsentDisplayName": "Access as user.",
				"Id": "a27ced89-6d4a-43bb-8b6e-cc382cf093cb",
				"IsEnabled": true,
				"Type": "User",
				"UserConsentDescription": "Allow application to interact with other systems on behalf of you.",
				"UserConsentDisplayName": "Allow application to act on your behalf.",
				"Value": "access_as_user"
			}
		],
		"PreAuthorizedApplications":
		[
			{
				"AppId": "1fec8e78-bce4-4aaf-ab1b-5451cc387264",
				"DelegatedPermissionIds":
				[
					"a27ced89-6d4a-43bb-8b6e-cc382cf093cb"
				]
			},
			{
				"AppId": "5e3ce6c0-2b1f-4285-8d4b-75ee78787346",
				"DelegatedPermissionIds":
				[
					"a27ced89-6d4a-43bb-8b6e-cc382cf093cb"
				]
			}
		]
	},
	"AppId": "a3a48dab-2a79-4d7b-8fce-c3f3edff48eb",
	"Id": "00e2f4d3-2a80-45bb-aa98-050d4ffc0a78",
	"IdentifierUris":
	[
		"api://botid-00e2f4d3-2a80-45bb-aa98-050d4ffc0a78"
	],
	"Notes": "Please contact owners for any questions.",
	"OptionalClaims":
	{
		"AccessToken":
		[
			{
				"Name": "upn"
			},
			{
				"Name": "idtyp"
			}
		]
	},
	"Owners":
	[
		{
			"id": "aa9c1d25-07fa-4c3e-9e70-66353ab0a96f"
		}
	],
	"PasswordCredentials":
	[
		{
			"DisplayName": "default",
			"KeyId": "d1a1d26a-4d7a-489a-af88-91338d7cc2cc"
		}
	],
	"PublisherDomain": "gostas.dev",
	"RequiredResourceAccess":
	[
		{
			"ResourceAppId": "00000003-0000-0000-c000-000000000000",
			"ResourceAccess":
			[
				{
					"id": "14dad69e-099b-42c9-810b-d002981feec1",
					"type": "Scope"
				},
				{
					"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
					"type": "Scope"
				},
				{
					"id": "df021288-bdef-4463-88db-98f22de89214",
					"type": "Role"
				},
				{
					"id": "908de74d-f8b2-4d6b-a9ed-2a17b3b78179",
					"type": "Role"
				}
			]
		}
	],
	"SignInAudience": "AzureADMyOrg",
	"Web":
	{
		"ImplicitGrantSettings":
		{
			"EnableAccessTokenIssuance": true,
			"EnableIdTokenIssuance": true
		},
		"RedirectUris":
		[
			"https://token.botframework.com/.auth/web/redirect"
		]
	}
}

@ramfattah

Part 2
we utilize Azure Bicep and ARM templates to provision Azure Bot Service
here is a sample of azure bot service arm template (default values are omitted)

Please note:

  1. We utilize User Assigned Managed Service Identity
{
    "name": "stas-teams-dev-t1",
    "type": "Microsoft.BotService/botServices",
    "location": "global",
    "sku":
    {
        "name": "F0"
    },
    "kind": "azurebot",
    "properties":
    {
        "displayName": "teams-dev-t1",
        "description": "Your personal assistant.",
        "iconUrl": "https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png",
        "endpoint": "https://stas-teams-dev-t1.azurewebsites.net/message",
        "msaAppId": "e92dc380-6e3f-4337-8d05-03941d7012ac",
        "msaAppTenantId": "a2096e5a-09e7-4fe4-bdf2-57fa785b8ede",
        "msaAppType": "UserAssignedMSI",
        "msaAppMSIResourceId": "/subscriptions/66ef014e-adb6-4868-9182-52fe0deeeb00/resourceGroups/stas-teams-dev-t1/providers/Microsoft.ManagedIdentity/userAssignedIdentities/stas-teams-dev-t1",
        "developerAppInsightKey": "b0b64ec8-2993-4b1f-aa68-0bdea3647a62",
        "developerAppInsightsApplicationId": "c2d8c75c-d3e9-4430-9c7f-df717be15d65",
        "tenantId": "a2096e5a-09e7-4fe4-bdf2-57fa785b8ede",
        "disableLocalAuth": true
    }
}

@ramfattah

Part 3
we utilize Azure Bicep and ARM templates to provision Azure Bot Service Connection
here is a sample of azure bot service connection arm template (default values are omitted)

Please note:

  1. We explicitly specify EntraID tenantId, because we build Single Tenant solution
  2. We specify tokenExchangeUrl, because it is needed by Teams to exchange token and make Seamless SSO
{
  "name": "stas-teams-dev-t1/default",
  "type": "Microsoft.BotService/botServices/connections",
  "location": "global",
  "properties":
  {
    "clientId": "a3a48dab-2a79-4d7b-8fce-c3f3edff48eb",
    "clientSecret": null,
    "scopes": "api://botid-a3a48dab-2a79-4d7b-8fce-c3f3edff48eb/access_as_user",
    "serviceProviderId": "30dd229c-58e3-4a48-bdfd-91ec48eb906c",
    "serviceProviderDisplayName": "Azure Active Directory v2",
    "parameters":
    [
      {
        "key": "tokenExchangeUrl",
        "value": "api://botid-a3a48dab-2a79-4d7b-8fce-c3f3edff48eb"
      },
      {
        "key": "tenantId",
        "value": "a2096e5a-09e7-4fe4-bdf2-57fa785b8ede"
      },
      {
        "key": "clientId",
        "value": "a3a48dab-2a79-4d7b-8fce-c3f3edff48eb"
      },
      {
        "key": "clientSecret",
        "value": null
      },
      {
        "key": "scopes",
        "value": "api://botid-a3a48dab-2a79-4d7b-8fce-c3f3edff48eb/access_as_user"
      }
    ]
  }
}

@ramfattah

Part 4
we utilize Azure DevOps pipeline to automatically create Microsoft Teams Application Package.
here is a sample of Teams Application manifest. (default values are omitted)

{
	"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.16/MicrosoftTeams.schema.json",
	"bots":
	[
		{
			"botId": "e92dc380-6e3f-4337-8d05-03941d7012ac",
			"scopes":
			[
				"personal"
			]
		}
	],
	"developer":
	{
		"name": "Stas Sultanov",
	},
	"devicePermissions":
	[
		"openExternal",
		"notifications"
	],
	"id": "73f171ce-ba1d-42fa-9e02-0ea1149be8f4",
	"manifestVersion": "1.16",
	"name":
	{
		"short": "teams-dev-t1",
		"full": "Belle"
	},
	"packageName": "t1.dev.teams.gostas.dev",
	"validDomains":
	[
		"stas-teams-dev-t1.azurewebsites.net",
		"token.botframework.com"
	],
	"version": "1.1.0",
	"webApplicationInfo":
	{
		"id": "a3a48dab-2a79-4d7b-8fce-c3f3edff48eb",
		"resource": "api://botid-a3a48dab-2a79-4d7b-8fce-c3f3edff48eb"
	}
}

Thanks for the detail info @stas-sultanov. I'm attempting to reproduce this issue.

Will report back soon.

Hi @stas-sultanov,

I've been reviewing the following documentation and noticed an important detail regarding ngrok.

The Bot Framework SDK introduced support for user-assigned managed identity and single-tenant app types in version 4.15.0 for C# and JavaScript. However, these types aren't supported in other languages or in Bot Framework Composer, Emulator, or tunneling solutions like ngrok.

Given this, I wanted to check: during your development and testing phase in the Teams channel, are you using a tunneling solution like ngrok? If so, I wonder if this could be the root cause of the issue?

Hi @ramfattah ,
thank you for information.

We do not use ngrok or any other tunnelling service.

With help of Azure DevOps pipeline, we do the following:

  1. Provision App Registration for DEV environments.
  2. Provision dedicated DEV environment in Azure, using app Registration from step 1.
  3. Create Teams app.zip (manifest + icons), using app Registration from step 1 and Azure resources from step 2.
  4. Deploy .net application to DEV environment, using Azure resources from step 2.
  5. Install Teams app.zip to Teams application.
  6. Test

As I've mentioned earlier everything works, except Seamless SSO in Teams.

Hi @stas-sultanov,

If only we specify Token Exchange Url in Azure Bot Service Connection AADv2 we see it in
OAuthCard.TokenExchangeResource.
With such configuration bot service stop respond.

After specifying the Token Exchange Url in the Azure Bot Service Connection AADv2, which then appears in OAuthCard.TokenExchangeResource, do you encounter any errors or come across any log entries within the app service (web app)?

Closing due to lack of response. Please comment with answers and we can reopen if you need further assistance.