diff --git a/Composer/packages/client/src/pages/botProject/adapters/ABSChannels.tsx b/Composer/packages/client/src/pages/botProject/adapters/ABSChannels.tsx index 6a8c47d1ca..d1545fbf05 100644 --- a/Composer/packages/client/src/pages/botProject/adapters/ABSChannels.tsx +++ b/Composer/packages/client/src/pages/botProject/adapters/ABSChannels.tsx @@ -25,10 +25,15 @@ import { navigateTo } from '../../../utils/navigation'; import { botDisplayNameState, settingsState } from '../../../recoilModel'; import { AuthClient } from '../../../utils/authClient'; import { AuthDialog } from '../../../components/Auth/AuthDialog'; -import { armScopes } from '../../../constants'; -import { getTokenFromCache, isShowAuthDialog, userShouldProvideTokens } from '../../../utils/auth'; +import { + getTokenFromCache, + getTenantIdFromCache, + isShowAuthDialog, + userShouldProvideTokens, +} from '../../../utils/auth'; import httpClient from '../../../utils/httpUtil'; import { dispatcherState } from '../../../recoilModel'; +import { armScopes } from '../../../constants'; import { tableHeaderRow, tableRow, @@ -63,6 +68,7 @@ type AzureResourcePointer = { resourceName: string; resourceGroupName: string; microsoftAppId: string; + tenantId: string; }; type AzureChannelStatus = { @@ -117,32 +123,65 @@ export const ABSChannels: React.FC = (props) => { } }; - const onSelectProfile = async (_, opt) => { - if (opt.key === 'manageProfiles') { - TelemetryClient.track('ConnectionsAddNewProfile'); - navigateTo(`/bot/${projectId}/publish/all/#addNewPublishProfile`); - } else { - let newtoken = ''; - if (userShouldProvideTokens()) { - if (isShowAuthDialog(false)) { - setShowAuthDialog(true); + const getTokenInteractively = async (tenantId: string) => { + let newtoken = ''; + try { + // if tenantId is present, use this to retrieve the arm token. + // absence of a tenantId indicates this was a legacy (pre-tenant support) provisioning profile + if (!tenantId) { + const tenants = await AuthClient.getTenants(); + const cachedTenantId = getTenantIdFromCache(); + + if (tenants.length === 0) { + throw new Error('No Azure Directories were found.'); + } else if (cachedTenantId && tenants.map((t) => t.tenantId).includes(cachedTenantId)) { + tenantId = cachedTenantId; + } else { + tenantId = tenants[0].tenantId; } - newtoken = getTokenFromCache('accessToken'); + } + if (tenantId) { + newtoken = await AuthClient.getARMTokenForTenant(tenantId); } else { newtoken = await AuthClient.getAccessToken(armScopes); } - setToken(newtoken); + } catch (error) { + setErrorMessage(error.message || error.toString()); + setCurrentResource(undefined); + } + return newtoken; + }; + const onSelectProfile = async (_, opt) => { + if (opt.key === 'manageProfiles') { + TelemetryClient.track('ConnectionsAddNewProfile'); + navigateTo(`/bot/${projectId}/publish/all/#addNewPublishProfile`); + } else { // identify the publishing profile in the list const profile = publishTargets?.find((p) => p.name === opt.key); if (profile) { const config = JSON.parse(profile.configuration); - setCurrentResource({ - microsoftAppId: config?.settings?.MicrosoftAppId, - resourceName: config.botName || config.name, - resourceGroupName: config.resourceGroup || config.botName || config.name, - subscriptionId: config.subscriptionId, - }); + + let newtoken = ''; + if (userShouldProvideTokens()) { + if (isShowAuthDialog(false)) { + setShowAuthDialog(true); + } + newtoken = getTokenFromCache('accessToken'); + } else { + newtoken = await getTokenInteractively(config.tenantId); + } + setToken(newtoken); + + if (newtoken) { + setCurrentResource({ + microsoftAppId: config?.settings?.MicrosoftAppId, + resourceName: config.botName || config.name, + resourceGroupName: config.resourceGroup || config.botName || config.name, + tenantId: config.tenantId, + subscriptionId: config.subscriptionId, + }); + } } } }; @@ -321,16 +360,18 @@ export const ABSChannels: React.FC = (props) => { }; const hasAuth = async () => { - let newtoken = ''; - if (userShouldProvideTokens()) { - if (isShowAuthDialog(false)) { - setShowAuthDialog(true); + if (currentResource) { + let newtoken = ''; + if (userShouldProvideTokens()) { + if (isShowAuthDialog(false)) { + setShowAuthDialog(true); + } + newtoken = getTokenFromCache('accessToken'); + } else { + newtoken = await getTokenInteractively(currentResource.tenantId); } - newtoken = getTokenFromCache('accessToken'); - } else { - newtoken = await AuthClient.getAccessToken(armScopes); + setToken(newtoken); } - setToken(newtoken); }; const toggleService = (channel) => {