src/Authentication/MsalExtensions.cs (38 lines of code) (raw):
// Copyright (c) Microsoft. All rights reserved.
//
// Licensed under the MIT license.
using Microsoft.Identity.Client;
namespace Microsoft.Artifacts.Authentication;
public static partial class MsalExtensions
{
public static List<(IAccount Account, string CanonicalName)> GetApplicableAccounts(IEnumerable<IAccount> accounts, Guid authorityTenantId, string? loginHint)
{
var applicableAccounts = new List<(IAccount, string)>();
foreach (var account in accounts)
{
string canonicalName = $"{account.HomeAccountId?.TenantId}\\{account.Username}";
// If a login hint is provided and matches, try that first
if (!string.IsNullOrEmpty(loginHint) && account.Username == loginHint)
{
applicableAccounts.Insert(0, (account, canonicalName));
continue;
}
if (Guid.TryParse(account.HomeAccountId?.TenantId, out Guid accountTenantId))
{
if (accountTenantId == authorityTenantId)
{
applicableAccounts.Add((account, canonicalName));
}
else if (accountTenantId == MsalConstants.MsaAccountTenant && (authorityTenantId == MsalConstants.FirstPartyTenant || authorityTenantId == Guid.Empty))
{
applicableAccounts.Add((account, canonicalName));
}
}
}
return applicableAccounts;
}
public static AcquireTokenSilentParameterBuilder WithAccountTenantId(this AcquireTokenSilentParameterBuilder builder, IAccount account)
{
// Workaround for https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/3077
// Even if using the organizations tenant the presence of an MSA will attempt to use the consumers tenant
// which is not supported by the Azure DevOps application. Detect this case and use the first party tenant.
if (Guid.TryParse(account.HomeAccountId?.TenantId, out Guid accountTenantId) && accountTenantId == MsalConstants.MsaAccountTenant)
{
builder = builder.WithTenantId(MsalConstants.FirstPartyTenant.ToString());
}
return builder;
}
}