Skip to content

Commit cf2d280

Browse files
authored
fix issue: fails to migrate ADAL token for MSA account (#13292)
1 parent f231a35 commit cf2d280

File tree

4 files changed

+53
-7
lines changed

4 files changed

+53
-7
lines changed

src/Accounts/Accounts/Account/ConnectAzureRmAccount.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
using Microsoft.Azure.Commands.Common.Authentication;
2323
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
24+
using Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core;
2425
using Microsoft.Azure.Commands.Common.Authentication.Factories;
2526
using Microsoft.Azure.Commands.Common.Authentication.Models;
2627
using Microsoft.Azure.Commands.Profile.Common;
@@ -463,6 +464,12 @@ private void SetContextWithOverwritePrompt(Action<AzureRmProfile, RMProfileClien
463464
}
464465
}
465466

467+
private static IAzureContextContainer GetAzureContextContainer()
468+
{
469+
var provider = new ProtectedProfileProvider();
470+
return provider.Profile;
471+
}
472+
466473
/// <summary>
467474
/// Load global aliases for ARM
468475
/// </summary>
@@ -472,7 +479,8 @@ public void OnImport()
472479
try
473480
{
474481
#endif
475-
AzureSessionInitializer.InitializeAzureSession();
482+
AzureSessionInitializer.InitializeAzureSession();
483+
AzureSessionInitializer.MigrateAdalCache(AzureSession.Instance, GetAzureContextContainer);
476484
#if DEBUG
477485
if (!TestMockSupport.RunningMocked)
478486
{

src/Accounts/Authentication/Authentication/TokenCache/AdalTokenMigrator.cs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using System.Linq;
1717

1818
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
19+
using Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core;
1920
using Microsoft.Identity.Client;
2021
using Microsoft.Identity.Client.Extensions.Msal;
2122

@@ -24,13 +25,18 @@ namespace Microsoft.Azure.Commands.Common.Authentication.Authentication.TokenCac
2425
public class AdalTokenMigrator
2526
{
2627
protected const string PowerShellClientId = "1950a258-227b-4e31-a9cf-717495945fc2";
28+
private const string TenantsString = "Tenants";
29+
2730
private byte[] AdalToken { get; set; }
2831

2932
private bool HasRegistered { get; set; }
3033

31-
public AdalTokenMigrator(byte[] adalToken)
34+
private Lazy<IAzureContextContainer> ContextContainerInitializer { get; set; }
35+
36+
public AdalTokenMigrator(byte[] adalToken, Func<IAzureContextContainer> getContextContainer)
3237
{
3338
AdalToken = adalToken;
39+
ContextContainerInitializer = new Lazy<IAzureContextContainer>(getContextContainer);
3440
}
3541

3642
public void MigrateFromAdalToMsal()
@@ -85,7 +91,19 @@ public void MigrateFromAdalToMsal()
8591
}
8692

8793
var scopes = new string[] { string.Format("{0}{1}", environment.ActiveDirectoryServiceEndpointResourceId, ".default") };
88-
var token = clientApplication.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false).GetAwaiter().GetResult();
94+
95+
try
96+
{
97+
clientApplication.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false).GetAwaiter().GetResult();
98+
}
99+
catch //For MSA account, real AAD tenant must be specified, otherwise MSAL library will request token against its home tenant
100+
{
101+
var tenantId = GetTenantId(account.Username);
102+
if(!string.IsNullOrEmpty(tenantId))
103+
{
104+
clientApplication.AcquireTokenSilent(scopes, account).WithAuthority(environment.ActiveDirectoryAuthority, tenantId).ExecuteAsync().ConfigureAwait(false).GetAwaiter().GetResult();
105+
}
106+
}
89107
//TODO: Set HomeAccountId for migration
90108
}
91109
catch
@@ -96,5 +114,20 @@ public void MigrateFromAdalToMsal()
96114
}
97115
cacheHelper?.UnregisterCache(clientApplication.UserTokenCache);
98116
}
117+
118+
private string GetTenantId(string accountId)
119+
{
120+
var contextContainer = ContextContainerInitializer.Value;
121+
string tenantId = null;
122+
if (contextContainer != null)
123+
{
124+
var matchedAccount = contextContainer?.Accounts?.FirstOrDefault(account => string.Equals(account.Id, accountId, StringComparison.InvariantCultureIgnoreCase));
125+
if (matchedAccount != null && matchedAccount.ExtendedProperties.ContainsKey(TenantsString))
126+
{
127+
tenantId = matchedAccount.ExtendedProperties[TenantsString]?.Split(',')?.FirstOrDefault();
128+
}
129+
}
130+
return tenantId;
131+
}
99132
}
100133
}

src/Accounts/Authentication/AzureSessionInitializer.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using Hyak.Common;
2121

2222
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
23+
using Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core;
2324
using Microsoft.Azure.Commands.Common.Authentication.Authentication.TokenCache;
2425
using Microsoft.Azure.Commands.Common.Authentication.Factories;
2526
using Microsoft.Azure.Commands.Common.Authentication.Properties;
@@ -98,14 +99,17 @@ static bool MigrateSettings(IDataStore store, string oldProfileDirectory, string
9899
return false;
99100
}
100101

101-
static void MigrateAdalCache(AzureSession session, IDataStore store, string adalCachePath, string msalCachePath)
102+
public static void MigrateAdalCache(IAzureSession session, Func<IAzureContextContainer> getContextContainer)
102103
{
103104
if (session.ARMContextSaveMode == ContextSaveMode.Process)
104105
{
105106
// Don't attempt to migrate if context autosave is disabled
106107
return;
107108
}
108109

110+
var adalCachePath = Path.Combine(session.ProfileDirectory, "TokenCache.dat");
111+
var msalCachePath = Path.Combine(session.TokenCacheDirectory, "msal.cache");
112+
var store = session.DataStore;
109113
if (!store.FileExists(adalCachePath) || store.FileExists(msalCachePath))
110114
{
111115
// Return if
@@ -127,7 +131,7 @@ static void MigrateAdalCache(AzureSession session, IDataStore store, string adal
127131

128132
if(adalData != null && adalData.Length > 0)
129133
{
130-
new AdalTokenMigrator(adalData).MigrateFromAdalToMsal();
134+
new AdalTokenMigrator(adalData, getContextContainer).MigrateFromAdalToMsal();
131135
}
132136
}
133137

@@ -232,7 +236,7 @@ static IAzureSession CreateInstance(IDataStore dataStore = null)
232236
session.ARMProfileFile = autoSave.ContextFile;
233237
session.TokenCacheDirectory = autoSave.CacheDirectory;
234238
session.TokenCacheFile = autoSave.CacheFile;
235-
MigrateAdalCache(session, dataStore, oldCachePath, Path.Combine(cachePath, "msal.cache"));
239+
236240
InitializeDataCollection(session);
237241
session.RegisterComponent(HttpClientOperationsFactory.Name, () => HttpClientOperationsFactory.Create());
238242
session.TokenCache = session.TokenCache ?? new AzureTokenCache();

src/Accounts/Authentication/Utilities/CustomAssemblyResolver.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ public static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEvent
5555
AssemblyName name = new AssemblyName(args.Name);
5656
if (NetFxPreloadAssemblies.TryGetValue(name.Name, out Version version))
5757
{
58-
if (version >= name.Version && version.Major == name.Version.Major)
58+
//For Newtonsoft.Json, allow to use bigger version to replace smaller version
59+
if (version >= name.Version && (version.Major == name.Version.Major || string.Equals(name.Name, "Newtonsoft.Json", StringComparison.OrdinalIgnoreCase)))
5960
{
6061
string requiredAssembly = Path.Combine(PreloadAssemblyFolder, $"{name.Name}.dll");
6162
return Assembly.LoadFrom(requiredAssembly);

0 commit comments

Comments
 (0)