Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Core/Authentication/Entra/EntraAuthentication.Caching.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,22 @@ private Task RegisterCacheAsync(IConfidentialClientApplication app) =>

private async Task RegisterCacheAsync(ITokenCache cache, StoragePropertiesBuilder propsBuilder)
{
using var _ = Trace2.StartRegion(Trace2Category, "cache_init");

Context.Trace.WriteLine("Configuring MSAL token cache...");

if (!PlatformUtils.IsWindows() && !PlatformUtils.IsPosix())
{
string osType = PlatformUtils.GetPlatformInformation().OperatingSystemType;
Trace2.WriteData(Trace2Category, "result", "unsupported");
Context.Trace.WriteLine($"Token cache integration is not supported on {osType}.");
return;
}

// We use the MSAL extension library to provide us consistent cache file access semantics (synchronisation, etc)
// as other GCM processes, and other Microsoft developer tools such as Visual Studio.
MsalCacheHelper helper = null;
string cacheResult = "ok";
try
{
StorageCreationProperties storageProps = propsBuilder(useLinuxFallback: false);
Expand Down Expand Up @@ -67,19 +71,22 @@ private async Task RegisterCacheAsync(ITokenCache cache, StoragePropertiesBuilde
// On Linux the SecretService/keyring might not be available so we must fall-back to a plaintext file.
Context.Console.WriteWarning("using plain-text fallback token cache");
Context.Trace.WriteLine("Using fall-back plaintext token cache on Linux.");
cacheResult = "linux_fallback";
StorageCreationProperties storageProps = propsBuilder(useLinuxFallback: true);
helper = await MsalCacheHelper.CreateAsync(storageProps);
}
}

if (helper is null)
{
Trace2.WriteData(Trace2Category, "result", "failed");
Context.Console.WriteError("failed to set up token cache!");
Context.Trace.WriteLine("Failed to integrate with token cache!");
}
else
{
helper.RegisterCache(cache);
Trace2.WriteData(Trace2Category, "result", cacheResult);
Context.Trace.WriteLine("Token cache configured.");
}
}
Expand All @@ -105,6 +112,7 @@ internal StorageCreationProperties CreateUserTokenCacheProps(bool useLinuxFallba
// The shared cache is used by other Microsoft developer tools such as Visual Studio.
if (PublicClientConfig.UseSharedCache)
{
Trace2.WriteData(Trace2Category, "cache/type", "msdevtools");
Context.Trace.WriteLine("Using shared Microsoft Developer MSAL cache");

if (PlatformUtils.IsWindows())
Expand All @@ -127,6 +135,10 @@ internal StorageCreationProperties CreateUserTokenCacheProps(bool useLinuxFallba
linuxAttr1 = new("MsalClientID", "Microsoft.Developer.IdentityService");
linuxAttr2 = new("Microsoft.Developer.IdentityService", "1.0.0.0");
}
else
{
Trace2.WriteData(Trace2Category, "cache/type", "gcm");
}

var builder = new StorageCreationPropertiesBuilder(cacheFileName, cacheDirectory)
.WithMacKeyChain(macService, macAccount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public partial class EntraAuthentication
public async Task<IEntraAuthenticationResult> GetTokenForServicePrincipalAsync(
string[] scopes, ServicePrincipalIdentity sp, CancellationToken ct = default)
{
using var _ = Trace2.StartRegion(Trace2Category, "token_service_principal");

Context.Trace.WriteLine($"Creating confidential client for service principal '{sp.Id}' in tenant '{sp.TenantId}'...");
var builder = ConfidentialClientApplicationBuilder.Create(sp.Id)
.WithTenantId(sp.TenantId)
Expand All @@ -20,11 +22,13 @@ public async Task<IEntraAuthenticationResult> GetTokenForServicePrincipalAsync(

if (sp.Certificate is not null)
{
Trace2.WriteData(Trace2Category, "credential/type", "certificate");
Context.Trace.WriteLine($"Using service principal certificate: {sp.Certificate.Thumbprint}");
builder.WithCertificate(sp.Certificate);
}
else if (!string.IsNullOrWhiteSpace(sp.ClientSecret))
{
Trace2.WriteData(Trace2Category, "credential/type", "secret");
Context.Trace.WriteLineSecrets("Using service principal secret: {0}", [sp.ClientSecret]);
builder.WithClientSecret(sp.ClientSecret);
}
Expand All @@ -33,6 +37,7 @@ public async Task<IEntraAuthenticationResult> GetTokenForServicePrincipalAsync(
throw new ArgumentException($"Service principal '{sp.Id}' must have either a certificate or client secret.", nameof(sp));
}

Trace2.WriteData(Trace2Category, "send_x5c", sp.SendX5C ? "true" : "false");
Context.Trace.WriteLine($"SendX5C is '{sp.SendX5C}'");

IConfidentialClientApplication app = builder.Build();
Expand All @@ -49,6 +54,12 @@ public async Task<IEntraAuthenticationResult> GetTokenForServicePrincipalAsync(
public async Task<IEntraAuthenticationResult> GetTokenForManagedIdentityAsync(
string resource, ManagedIdentity mi, CancellationToken ct = default)
{
using var _ = Trace2.StartRegion(Trace2Category, "token_managed_identity");

// Record whether the identity is system- or user-assigned, but not the
// client or resource ID itself, which identifies a specific identity.
Trace2.WriteData(Trace2Category, "mi/kind", mi.Id.Split("://")[0]);

Context.Trace.WriteLine($"Creating confidential client for managed identity '{mi.Id}'...");
var builder = ManagedIdentityApplicationBuilder.Create(mi)
.WithHttpClientFactory(_httpFactory)
Expand All @@ -66,6 +77,9 @@ public async Task<IEntraAuthenticationResult> GetTokenForManagedIdentityAsync(
public async Task<IEntraAuthenticationResult> GetTokenUsingWorkloadFederationAsync(
string[] scopes, WorkloadFederationOptions fedOpts, CancellationToken ct = default)
{
using var _ = Trace2.StartRegion(Trace2Category, "token_workload_federation");
Trace2.WriteData(Trace2Category, "scenario", fedOpts.Scenario.ToString().ToLowerInvariant());

Context.Trace.WriteLine(
$"Creating confidential client for federation with client ID '{fedOpts.ClientId}' and tenant ID '{fedOpts.TenantId}'...");
Context.Trace.WriteLine($"Federation scenario: {fedOpts.Scenario}");
Expand Down Expand Up @@ -115,6 +129,8 @@ private async Task<string> GetClientAssertion(WorkloadFederationOptions fedOpts,

private async Task<string> GetGitHubOidcToken(Uri requestUri, string audience, string requestToken)
{
using var _ = Trace2.StartRegion(Trace2Category, "github_oidc");

using HttpClient http = Context.HttpClientFactory.CreateClient();

UriBuilder ub = new UriBuilder(requestUri);
Expand Down
Loading
Loading