public async Task ATS_AccountMatchingInWAM_MatchingHomeAccId_Async()
        {
            string homeAccId = $"{TestConstants.Uid}.{TestConstants.Utid}";

            // Arrange
            using (var harness = CreateTestHarness())
            {
                var wamAccountProvider = new WebAccountProvider("id", "*****@*****.**", null);
                var requestParams      = harness.CreateAuthenticationRequestParameters(TestConstants.AuthorityConsumerTidTenant); // MSA
                var webAccount         = new WebAccount(wamAccountProvider, "*****@*****.**", WebAccountState.Connected);
                IReadOnlyList <WebAccount> webAccounts = new List <WebAccount>()
                {
                    webAccount
                };
                var webTokenRequest         = new WebTokenRequest(wamAccountProvider);
                var webTokenResponseWrapper = Substitute.For <IWebTokenRequestResultWrapper>();
                webTokenResponseWrapper.ResponseStatus.Returns(WebTokenRequestStatus.Success);
                var webTokenResponse = new WebTokenResponse();
                webTokenResponseWrapper.ResponseData.Returns(new List <WebTokenResponse>()
                {
                    webTokenResponse
                });

                _wamProxy.FindAllWebAccountsAsync(wamAccountProvider, TestConstants.ClientId).Returns(Task.FromResult(webAccounts));

                // WAM can give MSAL the home account ID of a Wam account, which MSAL matches to a WAM account
                _msaPlugin.GetHomeAccountIdOrNull(webAccount).Returns(homeAccId);

                _msaPlugin.CreateWebTokenRequestAsync(
                    wamAccountProvider,
                    requestParams,
                    isForceLoginPrompt: false,
                    isAccountInWam: true,
                    isInteractive: false)
                .Returns(Task.FromResult(webTokenRequest));

                requestParams.Account = new Account(
                    homeAccId,                   // matching in on home acc id
                    "*****@*****.**", // matching is not on UPN
                    null);                       // account does not have wam_id, might be coming directly from WAM

                var atsParams = new AcquireTokenSilentParameters();
                _webAccountProviderFactory.GetAccountProviderAsync(null).ReturnsForAnyArgs(Task.FromResult(wamAccountProvider));

                _wamProxy.GetTokenSilentlyAsync(webAccount, webTokenRequest).
                Returns(Task.FromResult(webTokenResponseWrapper));
                _msaPlugin.ParseSuccesfullWamResponse(webTokenResponse).Returns(_msalTokenResponse);


                // Act
                var result = await _wamBroker.AcquireTokenSilentAsync(requestParams, atsParams).ConfigureAwait(false);

                // Assert
                Assert.AreSame(_msalTokenResponse, result);
            }
        }
        /// <summary>
        /// The algorithm here is much more complex in order to workaround a limitation in the AAD plugin's
        /// handling of guest accounts:
        ///
        /// 1. Read the accounts from WAM.AADPlugin
        /// 2. For each account, we need to find its home_account_id as the one from WAM may not be correct
        /// 3. If we can find a cached account with the same LocalAccountId or UPN, use it
        /// 4. If not, make a simple silent token request and use the client info provided
        /// </summary>
        public async Task <IReadOnlyList <IAccount> > GetAccountsAsync(
            string clientId,
            AuthorityInfo authorityInfo,
            Cache.ICacheSessionManager cacheSessionManager,
            Instance.Discovery.IInstanceDiscoveryManager instanceDiscoveryManager)
        {
            var webAccountProvider = await _webAccountProviderFactory.GetAccountProviderAsync("organizations").ConfigureAwait(false);

            var wamAccounts = await _wamProxy.FindAllWebAccountsAsync(webAccountProvider, clientId).ConfigureAwait(false);

            if (wamAccounts.Count > 0)
            {
                var webAccountEnvs = wamAccounts
                                     .Select(w =>
                {
                    _wamProxy.TryGetAccountProperty(w, "Authority", out string accountAuthority);
                    if (accountAuthority != null)
                    {
                        return((new Uri(accountAuthority)).Host);
                    }
                    else
                    {
                        _logger.WarningPii(
                            $"[WAM AAD Provider] Could not convert the WAM account {w.UserName} (id: {w.Id}) to an MSAL account because the Authority could not be found",
                            $"[WAM AAD Provider] Could not convert the WAM account {w.Id} to an MSAL account because the Authority could not be found");

                        return(null);
                    }
                })
                                     .Where(a => a != null);

                var instanceMetadata = await instanceDiscoveryManager.GetMetadataEntryTryAvoidNetworkAsync(authorityInfo, webAccountEnvs, cacheSessionManager.RequestContext)
                                       .ConfigureAwait(false);

                var accountsFromCache = await cacheSessionManager.GetAccountsAsync().ConfigureAwait(false);

                var msalAccountTasks = wamAccounts
                                       .Select(
                    async webAcc =>
                    await ConvertToMsalAccountOrNullAsync(
                        clientId,
                        webAcc,
                        instanceMetadata,
                        cacheSessionManager,
                        accountsFromCache).ConfigureAwait(false));

                var msalAccounts = (await Task.WhenAll(msalAccountTasks).ConfigureAwait(false)).Where(a => a != null).ToList();

                _logger.Info($"[WAM AAD Provider] GetAccountsAsync converted {msalAccounts.Count} accounts from {wamAccounts.Count} WAM accounts");
                return(msalAccounts);
            }

            _logger.Info("[WAM AAD provider] No accounts found.");
            return(Array.Empty <IAccount>());
        }
Exemplo n.º 3
0
        /// <summary>
        /// Generally the MSA plugin will NOT return the accounts back to the app. This is due
        /// to privacy concerns. However, some test apps are allowed to do this, hence the code.
        /// Normal 1st and 3rd party apps must use AcquireTokenInteractive to login first, and then MSAL will
        /// save the account for later use.
        /// </summary>
        public async Task <IEnumerable <IAccount> > GetAccountsAsync(string clientID)
        {
            var webAccounProvider = await _webAccountProviderFactory.GetAccountProviderAsync("consumers").ConfigureAwait(false);

            var webAccounts = await _wamProxy.FindAllWebAccountsAsync(webAccounProvider, clientID).ConfigureAwait(false);

            var msalAccounts = webAccounts
                               .Select(webAcc => ConvertToMsalAccountOrNull(webAcc))
                               .Where(a => a != null)
                               .ToList();

            _logger.Info($"[WAM MSA Plugin] GetAccountsAsync converted {webAccounts.Count()} MSAL accounts");
            return(msalAccounts);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Generally the MSA plugin will NOT return the accounts back to the app. This is due
        /// to privacy concerns. However, some test apps are allowed to do this, hence the code.
        /// Normal 1st and 3rd party apps must use AcquireTokenInteractive to login first, and then MSAL will
        /// save the account for later use.
        /// </summary>
        public async Task <IReadOnlyList <IAccount> > GetAccountsAsync(
            string clientID,
            string authority,
            ICacheSessionManager cacheSessionManager,
            IInstanceDiscoveryManager instanceDiscoveryManager)
        {
            var webAccounProvider = await _webAccountProviderFactory.GetAccountProviderAsync("consumers").ConfigureAwait(false);

            var webAccounts = await _wamProxy.FindAllWebAccountsAsync(webAccounProvider, clientID).ConfigureAwait(false);

            var msalAccounts = webAccounts
                               .Select(webAcc => ConvertToMsalAccountOrNull(webAcc))
                               .Where(a => a != null)
                               .ToList();

            _logger.Info($"[WAM MSA Plugin] GetAccountsAsync converted {webAccounts.Count} MSAL accounts");
            return(msalAccounts);
        }
Exemplo n.º 5
0
        private async Task <WebAccount> FindWamAccountForMsalAccountAsync(
            WebAccountProvider provider,
            IWamPlugin wamPlugin,
            IAccount msalAccount,
            string loginHint,
            string clientId)
        {
            if (msalAccount == null && string.IsNullOrEmpty(loginHint))
            {
                return(null);
            }

            Account accountInternal = (msalAccount as Account);

            if (accountInternal?.WamAccountIds != null &&
                accountInternal.WamAccountIds.TryGetValue(clientId, out string wamAccountId))
            {
                _logger.Info("WAM will try to find an account based on the WAM account id from the cache");
                WebAccount result = await _wamProxy.FindAccountAsync(provider, wamAccountId).ConfigureAwait(false);

                if (result != null)
                {
                    return(result);
                }

                _logger.Warning("WAM account was not found for given WAM account id.");
            }

            var wamAccounts = await _wamProxy.FindAllWebAccountsAsync(provider, clientId).ConfigureAwait(false);

            return(MatchWamAccountToMsalAccount(
                       wamPlugin,
                       msalAccount,
                       loginHint,
                       wamAccounts));
        }
Exemplo n.º 6
0
        public async Task GetAccounts_WamAccounts_NoAuthority_Async()
        {
            // Arrange
            using (MockHttpAndServiceBundle harness = CreateTestHarness())
            {
                var wamAccountProvider = new WebAccountProvider("id", "*****@*****.**", null);
                _webAccountProviderFactory.GetAccountProviderAsync("organizations").Returns(wamAccountProvider);
                var wamAccount = new WebAccount(wamAccountProvider, "*****@*****.**", WebAccountState.Connected);
                // no authority ... skip these accounts
                _wamProxy.FindAllWebAccountsAsync(wamAccountProvider, TestConstants.ClientId).Returns(new[] { wamAccount });

                // Act
                var accounts = await _aadPlugin.GetAccountsAsync(
                    TestConstants.ClientId,
                    AuthorityInfo.FromAuthorityUri(TestConstants.AuthorityCommonTenant, true),
                    _cacheSessionManager,
                    _instanceDiscoveryManager).ConfigureAwait(false);

                // Assert
                Assert.AreEqual(0, accounts.Count());
            }
        }