/
PCACache.cs
102 lines (89 loc) · 4.22 KB
/
PCACache.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Authentication.MSALWrapper
{
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Extensions.Logging;
using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Extensions.Msal;
/// <summary>
/// The PCA cache class.
/// </summary>
internal class PCACache
{
// OSX
private const string MacOSAccountName = "MSALCache";
private const string MacOSServiceName = "Microsoft.Developer.IdentityService";
private const string OSXKeyChainCategory = "azureauth";
// Linux
private const string LinuxKeyRingSchema = "com.microsoft.identity.tokencache";
private const string LinuxKeyRingCollection = "default";
private const string LinuxKeyRingLabel = "MSAL token cache";
private static KeyValuePair<string, string> linuxKeyRingAttr1 = new KeyValuePair<string, string>("Version", "1");
private static KeyValuePair<string, string> linuxKeyRingAttr2 = new KeyValuePair<string, string>("ProductGroup", "Microsoft Develoepr Tools");
private readonly ILogger logger;
private readonly string osxKeyChainSuffix;
private readonly string cacheDir;
private readonly string cacheFileName;
/// <summary>
/// Initializes a new instance of the <see cref="PCACache"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="tenantId">The tenant id.</param>
internal PCACache(ILogger logger, Guid tenantId)
{
this.logger = logger;
this.osxKeyChainSuffix = $"{OSXKeyChainCategory}.{tenantId}";
this.cacheFileName = $"msal_{tenantId}.cache";
this.cacheDir = this.GetCacheServiceFolder();
}
/// <summary>
/// Sets up the token cache.
/// </summary>
/// <param name="userTokenCache">An <see cref="ITokenCache"/> to use.</param>
/// <param name="errors">The errors list to append error encountered to.</param>
public void SetupTokenCache(ITokenCache userTokenCache, IList<Exception> errors)
{
var cacheDisabled = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(Constants.OEAUTH_MSAL_DISABLE_CACHE));
if (cacheDisabled)
{
return;
}
var osxKeychainItem = $"{MacOSServiceName}.{this.osxKeyChainSuffix}";
var storageProperties = new StorageCreationPropertiesBuilder(this.cacheFileName, this.cacheDir)
.WithLinuxKeyring(LinuxKeyRingSchema, LinuxKeyRingCollection, LinuxKeyRingLabel, linuxKeyRingAttr1, linuxKeyRingAttr2)
.WithMacKeyChain(osxKeychainItem, MacOSAccountName)
.Build();
try
{
MsalCacheHelper cacher = MsalCacheHelper.CreateAsync(storageProperties).Result;
cacher.VerifyPersistence();
cacher.RegisterCache(userTokenCache);
}
catch (MsalCachePersistenceException ex)
{
this.logger.LogWarning($"MSAL token cache verification failed.\n{ex.Message}\n");
errors.Add(ex);
}
catch (AggregateException ex) when (ex.InnerException.Message.Contains("Could not get access to the shared lock file"))
{
var exceptionMessage = ex.ToFormattedString();
errors.Add(ex);
this.logger.LogError("An unexpected error occured creating the cache.");
throw new Exception(exceptionMessage);
}
}
/// <summary>
/// Gets the absolute path of the cache folder. Only available on Windows.
/// </summary>
/// <returns>The absolute path of the cache folder.</returns>
private string GetCacheServiceFolder()
{
string appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string absolutePath = Path.Combine(appData, ".IdentityService");
return absolutePath;
}
}
}