/// <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>()); }
public async Task <MsalTokenResponse> AcquireTokenSilentAsync( AuthenticationRequestParameters authenticationRequestParameters, AcquireTokenSilentParameters acquireTokenSilentParameters) { var cancellationToken = authenticationRequestParameters.RequestContext.UserCancellationToken; MsalTokenResponse msalTokenResponse = null; _logger.Verbose("[WamBroker] Acquiring token silently."); using (var core = new NativeInterop.Core()) using (var authParams = WamAdapters.GetCommonAuthParameters(authenticationRequestParameters, _wamOptions.MsaPassthrough)) { using (var account = await core.ReadAccountByIdAsync( acquireTokenSilentParameters.Account.HomeAccountId.ObjectId, authenticationRequestParameters.CorrelationId.ToString("D"), cancellationToken).ConfigureAwait(false)) { if (account == null) { _logger.WarningPii( $"Could not find a WAM account for the selected user {acquireTokenSilentParameters.Account.Username}", "Could not find a WAM account for the selected user"); throw new MsalUiRequiredException( "wam_no_account_for_id", $"Could not find a WAM account for the selected user {acquireTokenSilentParameters.Account.Username}"); } using (NativeInterop.AuthResult result = await core.AcquireTokenSilentlyAsync( authParams, authenticationRequestParameters.CorrelationId.ToString("D"), account, cancellationToken).ConfigureAwait(false)) { if (result.IsSuccess) { msalTokenResponse = WamAdapters.ParseRuntimeResponse(result, authenticationRequestParameters, _logger); } else { WamAdapters.ThrowExceptionFromWamError(result, authenticationRequestParameters, _logger); } } } } return(msalTokenResponse); }
void ILegacyCachePersistence.WriteCache(byte[] serializedCache) { try { var s = new SecRecord(SecKind.GenericPassword) { Generic = NSData.FromString(LocalSettingsContainerName), Accessible = SecAccessible.Always, Service = NAME + " Service", Account = NAME + " cache", Label = NAME + " Label", Comment = NAME + " Cache", Description = "Storage for cache" }; if (_keychainGroup != null) { s.AccessGroup = _keychainGroup; } var err = SecKeyChain.Remove(s); if (err != SecStatusCode.Success) { string msg = "Failed to remove adal cache record: "; _logger.WarningPii(msg + err, msg); } if (serializedCache != null && serializedCache.Length > 0) { s.ValueData = NSData.FromArray(serializedCache); err = SecKeyChain.Add(s); if (err != SecStatusCode.Success) { string msg = "Failed to save adal cache record: "; _logger.WarningPii(msg + err, msg); } } } catch (Exception ex) { _logger.WarningPiiWithPrefix(ex, "Failed to save adal cache: "); } }
public static void TryThrowServiceException(string thumbprint, ThrottlingCache cache, ICoreLogger logger, string providerName) { if (cache.TryGetOrRemoveExpired(thumbprint, logger, out var ex)) { logger.WarningPii( $"[Throttling] Exception thrown because of throttling rule {providerName} - thumbprint: {thumbprint}", $"[Throttling] Exception thrown because of throttling rule {providerName}"); // mark the exception for logging purposes throw new MsalThrottledServiceException(ex); } }
private Account ConvertToMsalAccountOrNull(WebAccount webAccount) { if (!webAccount.Properties.TryGetValue("Authority", out string authority)) { _logger.WarningPii( $"[WAM AAD Provider] Could not convert the WAM account {webAccount.UserName} (id: {webAccount.Id}) to an MSAL account because the Authority could not be found", $"[WAM AAD Provider] Could not convert the WAM account {webAccount.Id} to an MSAL account because the Authority could not be found"); return(null); } string environment = (new Uri(authority)).Host; string homeAccountId = GetHomeAccountIdOrNull(webAccount); if (homeAccountId != null) { var msalAccount = new Account(homeAccountId, webAccount?.UserName, environment); return(msalAccount); } return(null); }
private void TryThrowException(string thumbprint, ICoreLogger logger) { if (ThrottlingCache.TryGetOrRemoveExpired(thumbprint, logger, out MsalServiceException ex) && ex is MsalUiRequiredException uiException) { logger.WarningPii( $"[Throttling] Exception thrown because of throttling rule UiRequired - thumbprint: {thumbprint}", $"[Throttling] Exception thrown because of throttling rule UiRequired "); // mark the exception for logging purposes throw new MsalThrottledUiRequiredException(uiException); } }
public MsalIdTokenCacheItem GetIdToken(MsalAccessTokenCacheItem accessTokenCacheItem) { string partitionKey = CacheKeyFactory.GetIdTokenKeyFromCachedItem(accessTokenCacheItem); IdTokenCacheDictionary.TryGetValue(partitionKey, out var partition); if (partition != null && partition.TryGetValue(accessTokenCacheItem.GetIdTokenItemKey().ToString(), out var idToken)) { return(idToken); } _logger.WarningPii( $"Could not find an id token for the access token with key {accessTokenCacheItem.GetKey()}", $"Could not find an id token for the access token for realm {accessTokenCacheItem.TenantId} "); return(null); }
public string GetHomeAccountIdOrNull(WebAccount webAccount) { if (!webAccount.Properties.TryGetValue("SafeCustomerId", out string cid)) { _logger.Warning("[WAM MSA Plugin] MSAL account cannot be created without MSA CID"); return(null); } if (!TryConvertCidToGuid(cid, out string localAccountId)) { _logger.WarningPii($"[WAM MSA Plugin] Invalid CID: {cid}", $"[WAM MSA Provider] Invalid CID, length {cid.Length}"); return(null); } if (localAccountId == null) { return(null); } string homeAccountId = localAccountId + "." + Constants.MsaTenantId; return(homeAccountId); }