Skip to content
Prev Previous commit
Next Next commit
msauth: add MSAL app token cache support for CCAs
Add app token cache support for confidential client applications
(service principals). This is a different cache than the one for user
tokens that is used by public client applications (for normal users).

We do not know of any other app token cache that we can share with
currently, so we just use our own in the GCM data directory.
  • Loading branch information
mjcheetham committed Aug 15, 2023
commit f00c859fbadc6543452d59d4b2bd3b56d5f7d2f5
38 changes: 36 additions & 2 deletions src/shared/Core/Authentication/MicrosoftAuthentication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ public async Task<IMicrosoftAuthenticationResult> GetTokenForUserAsync(

public async Task<IMicrosoftAuthenticationResult> GetTokenForServicePrincipalAsync(ServicePrincipalIdentity sp, string[] scopes)
{
IConfidentialClientApplication app = CreateConfidentialClientApplication(sp);
IConfidentialClientApplication app = await CreateConfidentialClientApplicationAsync(sp);

try
{
Expand Down Expand Up @@ -528,7 +528,7 @@ private async Task<IPublicClientApplication> CreatePublicClientApplicationAsync(
return app;
}

private IConfidentialClientApplication CreateConfidentialClientApplication(ServicePrincipalIdentity sp)
private async Task<IConfidentialClientApplication> CreateConfidentialClientApplicationAsync(ServicePrincipalIdentity sp)
{
var httpFactoryAdaptor = new MsalHttpClientFactoryAdaptor(Context.HttpClientFactory);

Expand All @@ -554,6 +554,8 @@ private IConfidentialClientApplication CreateConfidentialClientApplication(Servi

IConfidentialClientApplication app = appBuilder.Build();

await RegisterTokenCacheAsync(app.AppTokenCache, CreateAppTokenCacheProps, Context.Trace2);

return app;
}

Expand Down Expand Up @@ -713,6 +715,38 @@ internal static ManagedIdentityId GetManagedIdentity(string str)
throw new ArgumentException("Invalid managed identity value.", nameof(str));
}

/// <summary>
/// Create the properties for the application token cache. This is used by confidential client applications only
/// and is not shared between applications other than GCM.
/// </summary>
internal StorageCreationProperties CreateAppTokenCacheProps(bool useLinuxFallback)
{
const string cacheFileName = "app.cache";

// The confidential client MSAL cache is located at "%UserProfile%\.gcm\msal\app.cache" on Windows
// and at "~/.gcm/msal/app.cache" on UNIX.
string cacheDirectory = Path.Combine(Context.FileSystem.UserDataDirectoryPath, "msal");

// The keychain is used on macOS with the following service & account names
var builder = new StorageCreationPropertiesBuilder(cacheFileName, cacheDirectory)
.WithMacKeyChain("GitCredentialManager.MSAL", "AppCache");

if (useLinuxFallback)
{
builder.WithLinuxUnprotectedFile();
}
else
{
// The SecretService/keyring is used on Linux with the following collection name and attributes
builder.WithLinuxKeyring(cacheFileName,
"default", "AppCache",
new KeyValuePair<string, string>("MsalClientID", "GitCredentialManager.MSAL"),
new KeyValuePair<string, string>("GitCredentialManager.MSAL", "1.0.0.0"));
}

return builder.Build();
}

private static EmbeddedWebViewOptions GetEmbeddedWebViewOptions()
{
return new EmbeddedWebViewOptions
Expand Down