update to ADAL 2.14.201151115 version
This commit is contained in:
Родитель
8aa6567157
Коммит
5563bbe554
|
@ -1,15 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ARMClient.Authentication.Contracts;
|
||||
using ARMClient.Authentication.EnvironmentStorage;
|
||||
using ARMClient.Authentication.TenantStorage;
|
||||
using ARMClient.Authentication.TokenStorage;
|
||||
using ARMClient.Authentication.Utilities;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
|
@ -36,93 +35,80 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
|
||||
public async Task AcquireTokens()
|
||||
{
|
||||
var tokenCache = new Dictionary<TokenCacheKey, string>();
|
||||
|
||||
var authResult = await GetAuthorizationResult(tokenCache, Constants.AADTenantId);
|
||||
Trace.WriteLine(string.Format("Welcome {0} (Tenant: {1})", authResult.UserInfo.UserId, authResult.TenantId));
|
||||
this.TokenStorage.ClearCache();
|
||||
this.TenantStorage.ClearCache();
|
||||
|
||||
var tenantCache = await GetTokenForTenants(tokenCache, authResult);
|
||||
var tokenCache = new CustomTokenCache();
|
||||
var cacheInfo = await GetAuthorizationResult(tokenCache, Constants.AADTenantId);
|
||||
Utils.Trace.WriteLine(string.Format("Welcome {0} (Tenant: {1})", cacheInfo.DisplayableId, cacheInfo.TenantId));
|
||||
|
||||
var tenantCache = await GetTokenForTenants(tokenCache, cacheInfo);
|
||||
|
||||
this.TokenStorage.SaveCache(tokenCache);
|
||||
this.TenantStorage.SaveCache(tenantCache);
|
||||
}
|
||||
|
||||
public async Task<AuthenticationResult> GetTokenByTenant(string tenantId)
|
||||
public async Task<TokenCacheInfo> GetToken(string id, string resource)
|
||||
{
|
||||
var found = false;
|
||||
var tenantCache = this.TenantStorage.GetCache();
|
||||
if (tenantCache.ContainsKey(tenantId))
|
||||
if (String.IsNullOrEmpty(id))
|
||||
{
|
||||
found = true;
|
||||
return await GetRecentToken(resource);
|
||||
}
|
||||
|
||||
if (!found)
|
||||
string tenantId = null;
|
||||
var tenantCache = this.TenantStorage.GetCache();
|
||||
if (tenantCache.ContainsKey(id))
|
||||
{
|
||||
tenantId = id;
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(tenantId))
|
||||
{
|
||||
foreach (var tenant in tenantCache)
|
||||
{
|
||||
if (tenant.Value.subscriptions.Any(s => s.subscriptionId == tenantId))
|
||||
if (tenant.Value.subscriptions.Any(s => s.subscriptionId == id))
|
||||
{
|
||||
tenantId = tenant.Key;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
if (String.IsNullOrEmpty(tenantId))
|
||||
{
|
||||
return await GetRecentToken();
|
||||
return await GetRecentToken(resource);
|
||||
}
|
||||
|
||||
if (resource == null)
|
||||
{
|
||||
resource = id == tenantId ? Constants.AADGraphUrls[(int)AzureEnvironments] : Constants.CSMResource;
|
||||
}
|
||||
|
||||
var tokenCache = this.TokenStorage.GetCache();
|
||||
var authResults = tokenCache.Where(p => p.Key.TenantId == tenantId && String.Equals(p.Key.Resource, Constants.CSMResource, StringComparison.OrdinalIgnoreCase))
|
||||
.Select(p => AuthenticationResult.Deserialize(Encoding.UTF8.GetString(Convert.FromBase64String(p.Value)))).ToArray();
|
||||
if (authResults.Length <= 0)
|
||||
TokenCacheInfo cacheInfo;
|
||||
if (!tokenCache.TryGetValue(tenantId, resource, out cacheInfo))
|
||||
{
|
||||
return await GetRecentToken();
|
||||
return await GetRecentToken(resource);
|
||||
}
|
||||
|
||||
if (authResults.Length > 1)
|
||||
if (cacheInfo.ExpiresOn <= DateTimeOffset.UtcNow)
|
||||
{
|
||||
foreach (var authResult in authResults)
|
||||
{
|
||||
Trace.WriteLine(authResult.UserInfo.UserId);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Multiple users found. Please specify user argument!");
|
||||
cacheInfo = await RefreshToken(tokenCache, cacheInfo);
|
||||
this.TokenStorage.SaveCache(tokenCache);
|
||||
}
|
||||
else
|
||||
{
|
||||
var authResult = authResults[0];
|
||||
if (authResult.ExpiresOn <= DateTime.UtcNow)
|
||||
{
|
||||
authResult = await RefreshToken(tokenCache, authResult);
|
||||
this.TokenStorage.SaveCache(tokenCache);
|
||||
}
|
||||
|
||||
this.TokenStorage.SaveRecentToken(authResult);
|
||||
this.TokenStorage.SaveRecentToken(cacheInfo, resource);
|
||||
|
||||
return authResult;
|
||||
}
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
public async Task<AuthenticationResult> GetTokenBySubscription(string subscriptionId)
|
||||
public async Task<TokenCacheInfo> GetTokenBySpn(string tenantId, string appId, string appKey)
|
||||
{
|
||||
var tenantCache = this.TenantStorage.GetCache();
|
||||
var pairs = tenantCache.Where(p => p.Value.subscriptions.Any(subscription => subscriptionId == subscription.subscriptionId)).ToArray();
|
||||
if (pairs.Length == 0)
|
||||
{
|
||||
return await GetRecentToken();
|
||||
}
|
||||
this.TokenStorage.ClearCache();
|
||||
this.TenantStorage.ClearCache();
|
||||
|
||||
return await GetTokenByTenant(pairs[0].Key);
|
||||
}
|
||||
|
||||
public async Task<AuthenticationResult> GetTokenBySpn(string tenantId, string appId, string appKey)
|
||||
{
|
||||
var tokenCache = new Dictionary<TokenCacheKey, string>();
|
||||
|
||||
var authResult = GetAuthorizationResultByAppKey(tokenCache, tenantId, appId, appKey);
|
||||
var tokenCache = new CustomTokenCache();
|
||||
var cacheInfo = GetAuthorizationResultBySpn(tokenCache, tenantId, appId, appKey, Constants.CSMResource);
|
||||
|
||||
var tenantCache = new Dictionary<string, TenantCacheInfo>();
|
||||
var info = new TenantCacheInfo
|
||||
|
@ -130,23 +116,21 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
tenantId = tenantId
|
||||
};
|
||||
|
||||
//try
|
||||
//{
|
||||
// var aadToken = GetAuthorizationResultByAppKey(tokenCache, tenantId, appId, appKey, Constants.AADGraphUrls[(int)AzureEnvironments]);
|
||||
// var details = await GetTenantDetail(aadToken, tenantId);
|
||||
// info.displayName = details.displayName;
|
||||
// info.domain = details.verifiedDomains.First(d => d.@default).name;
|
||||
// Trace.WriteLine(String.Format("App: {0}, Tenant: {1} ({2})", appId, tenantId, details.verifiedDomains.First(d => d.@default).name));
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// Trace.WriteLine(String.Format("App: {0}, Tenant: {1} {2}", appId, tenantId, ex.Message));
|
||||
//}
|
||||
try
|
||||
{
|
||||
var aadToken = GetAuthorizationResultBySpn(tokenCache, tenantId, appId, appKey, Constants.AADGraphUrls[(int)AzureEnvironments]);
|
||||
var details = await GetTenantDetail(aadToken, tenantId);
|
||||
info.displayName = details.displayName;
|
||||
info.domain = details.verifiedDomains.First(d => d.@default).name;
|
||||
Utils.Trace.WriteLine(String.Format("App: {0}, Tenant: {1} ({2})", appId, tenantId, details.verifiedDomains.First(d => d.@default).name));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Utils.Trace.WriteLine(String.Format("App: {0}, Tenant: {1}", appId, tenantId));
|
||||
}
|
||||
|
||||
Trace.WriteLine(String.Format("App: {0}, Tenant: {1}", appId, tenantId));
|
||||
|
||||
var subscriptions = await GetSubscriptions(authResult);
|
||||
Trace.WriteLine(String.Format("\tThere are {0} subscriptions", subscriptions.Length));
|
||||
var subscriptions = await GetSubscriptions(cacheInfo);
|
||||
Utils.Trace.WriteLine(String.Format("\tThere are {0} subscriptions", subscriptions.Length));
|
||||
|
||||
info.subscriptions = subscriptions.Select(subscription => new SubscriptionCacheInfo
|
||||
{
|
||||
|
@ -156,73 +140,94 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
|
||||
foreach (var subscription in subscriptions)
|
||||
{
|
||||
Trace.WriteLine(String.Format("\tSubscription {0} ({1})", subscription.subscriptionId, subscription.displayName));
|
||||
Utils.Trace.WriteLine(String.Format("\tSubscription {0} ({1})", subscription.subscriptionId, subscription.displayName));
|
||||
}
|
||||
|
||||
tenantCache[tenantId] = info;
|
||||
|
||||
this.TokenStorage.SaveRecentToken(authResult);
|
||||
this.TokenStorage.SaveRecentToken(cacheInfo, Constants.CSMResource);
|
||||
this.TokenStorage.SaveCache(tokenCache);
|
||||
this.TenantStorage.SaveCache(tenantCache);
|
||||
|
||||
return authResult;
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
public async Task<AuthenticationResult> GetRecentToken()
|
||||
public async Task<TokenCacheInfo> GetTokenByUpn(string tenantId, string username, string password)
|
||||
{
|
||||
AuthenticationResult recentToken = this.TokenStorage.GetRecentToken();
|
||||
if (recentToken != null && recentToken.ExpiresOn <= DateTime.UtcNow)
|
||||
this.TokenStorage.ClearCache();
|
||||
this.TenantStorage.ClearCache();
|
||||
|
||||
var tokenCache = new CustomTokenCache();
|
||||
var cacheInfo = GetAuthorizationResultByUpn(tokenCache, tenantId, username, password, Constants.CSMResource);
|
||||
|
||||
var tenantCache = new Dictionary<string, TenantCacheInfo>();
|
||||
var info = new TenantCacheInfo
|
||||
{
|
||||
tenantId = tenantId
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var aadToken = GetAuthorizationResultByUpn(tokenCache, tenantId, username, password, Constants.AADGraphUrls[(int)AzureEnvironments]);
|
||||
var details = await GetTenantDetail(aadToken, tenantId);
|
||||
info.displayName = details.displayName;
|
||||
info.domain = details.verifiedDomains.First(d => d.@default).name;
|
||||
Utils.Trace.WriteLine(String.Format("User: {0}, Tenant: {1} ({2})", username, tenantId, details.verifiedDomains.First(d => d.@default).name));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Utils.Trace.WriteLine(String.Format("User: {0}, Tenant: {1}", username, tenantId));
|
||||
}
|
||||
|
||||
var subscriptions = await GetSubscriptions(cacheInfo);
|
||||
Utils.Trace.WriteLine(String.Format("\tThere are {0} subscriptions", subscriptions.Length));
|
||||
|
||||
info.subscriptions = subscriptions.Select(subscription => new SubscriptionCacheInfo
|
||||
{
|
||||
subscriptionId = subscription.subscriptionId,
|
||||
displayName = subscription.displayName
|
||||
}).ToArray();
|
||||
|
||||
foreach (var subscription in subscriptions)
|
||||
{
|
||||
Utils.Trace.WriteLine(String.Format("\tSubscription {0} ({1})", subscription.subscriptionId, subscription.displayName));
|
||||
}
|
||||
|
||||
tenantCache[tenantId] = info;
|
||||
|
||||
this.TokenStorage.SaveRecentToken(cacheInfo, Constants.CSMResource);
|
||||
this.TokenStorage.SaveCache(tokenCache);
|
||||
this.TenantStorage.SaveCache(tenantCache);
|
||||
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
protected async Task<TokenCacheInfo> GetRecentToken(string resource)
|
||||
{
|
||||
TokenCacheInfo cacheInfo = this.TokenStorage.GetRecentToken(resource);
|
||||
if (cacheInfo != null && cacheInfo.ExpiresOn <= DateTimeOffset.UtcNow)
|
||||
{
|
||||
var tokenCache = this.TokenStorage.GetCache();
|
||||
recentToken = await RefreshToken(tokenCache, recentToken);
|
||||
cacheInfo = await RefreshToken(tokenCache, cacheInfo);
|
||||
this.TokenStorage.SaveCache(tokenCache);
|
||||
this.TokenStorage.SaveRecentToken(recentToken);
|
||||
this.TokenStorage.SaveRecentToken(cacheInfo, resource);
|
||||
}
|
||||
|
||||
return recentToken;
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
protected async Task<AuthenticationResult> RefreshToken(Dictionary<TokenCacheKey, string> tokenCache, AuthenticationResult authResult)
|
||||
protected async Task<TokenCacheInfo> RefreshToken(CustomTokenCache tokenCache, TokenCacheInfo cacheInfo)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(authResult.RefreshToken))
|
||||
if (!String.IsNullOrEmpty(cacheInfo.RefreshToken))
|
||||
{
|
||||
authResult = await GetAuthorizationResult(tokenCache, authResult.TenantId, authResult.UserInfo.UserId);
|
||||
return await GetAuthorizationResultByRefreshToken(tokenCache, cacheInfo);
|
||||
}
|
||||
else if (tokenCache.Count == 1)
|
||||
else if (!String.IsNullOrEmpty(cacheInfo.AppId) && !String.IsNullOrEmpty(cacheInfo.AppKey))
|
||||
{
|
||||
var key = tokenCache.Keys.First();
|
||||
string tenantId, appId, appKey;
|
||||
GetApplicationInfo(key, out tenantId, out appId, out appKey);
|
||||
|
||||
if (!String.IsNullOrEmpty(tenantId) && !String.IsNullOrEmpty(appId) && !String.IsNullOrEmpty(appKey))
|
||||
{
|
||||
tokenCache.Clear();
|
||||
authResult = GetAuthorizationResultByAppKey(tokenCache, tenantId, appId, appKey);
|
||||
}
|
||||
return GetAuthorizationResultBySpn(tokenCache, cacheInfo.TenantId, cacheInfo.AppId, cacheInfo.AppKey, cacheInfo.Resource);
|
||||
}
|
||||
|
||||
return authResult;
|
||||
}
|
||||
|
||||
private void SaveApplicationInfo(TokenCacheKey key, string tenantId, string appId, string appKey)
|
||||
{
|
||||
key.TenantId = tenantId;
|
||||
key.ClientId = appId;
|
||||
key.UserId = appKey;
|
||||
}
|
||||
|
||||
private void GetApplicationInfo(TokenCacheKey key, out string tenantId, out string appId, out string appKey)
|
||||
{
|
||||
tenantId = key.TenantId;
|
||||
appId = key.ClientId;
|
||||
appKey = key.UserId;
|
||||
}
|
||||
|
||||
public async Task<string> GetAuthorizationHeader(string subscriptionId)
|
||||
{
|
||||
return (await(string.IsNullOrEmpty(subscriptionId)
|
||||
? GetRecentToken()
|
||||
: GetTokenBySubscription(subscriptionId: subscriptionId)).ConfigureAwait(false)).CreateAuthorizationHeader();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsCacheValid()
|
||||
|
@ -241,47 +246,72 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
{
|
||||
var tokenCache = this.TokenStorage.GetCache();
|
||||
var tenantCache = this.TenantStorage.GetCache();
|
||||
if (tokenCache.Count > 0)
|
||||
foreach (var cacheItem in tokenCache.GetValues(Constants.CSMResource))
|
||||
{
|
||||
foreach (var item in tokenCache.Where(k => String.Equals(k.Key.Resource, Constants.CSMResource, StringComparison.OrdinalIgnoreCase)))
|
||||
var tenantId = cacheItem.TenantId;
|
||||
|
||||
if (Constants.InfrastructureTenantIds.Contains(tenantId))
|
||||
{
|
||||
var key = item.Key;
|
||||
var value = item.Value;
|
||||
var authResult = AuthenticationResult.Deserialize(Encoding.UTF8.GetString(Convert.FromBase64String(value)));
|
||||
var tenantId = authResult.TenantId ?? key.TenantId;
|
||||
|
||||
if (Constants.InfrastructureTenantIds.Contains(tenantId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var details = tenantCache[tenantId];
|
||||
if (authResult.UserInfo != null)
|
||||
{
|
||||
var user = authResult.UserInfo.UserId;
|
||||
yield return string.Format("User: {0}, Tenant: {1} ({2})", user, tenantId, details.domain);
|
||||
}
|
||||
else
|
||||
{
|
||||
var appId = key.ClientId;
|
||||
yield return string.Format("App: {0}, Tenant: {1}", appId, tenantId);
|
||||
}
|
||||
|
||||
var subscriptions = details.subscriptions;
|
||||
yield return string.Format("\tThere are {0} subscriptions", subscriptions.Length);
|
||||
|
||||
foreach (var subscription in subscriptions)
|
||||
{
|
||||
yield return string.Format("\tSubscription {0} ({1})", subscription.subscriptionId, subscription.displayName);
|
||||
}
|
||||
yield return string.Empty;
|
||||
continue;
|
||||
}
|
||||
|
||||
var details = tenantCache[tenantId];
|
||||
if (!String.IsNullOrEmpty(cacheItem.DisplayableId))
|
||||
{
|
||||
yield return string.Format("User: {0}, Tenant: {1} ({2})", cacheItem.DisplayableId, tenantId, details.domain);
|
||||
}
|
||||
else if (!String.IsNullOrEmpty(cacheItem.AppId))
|
||||
{
|
||||
yield return string.Format(String.IsNullOrEmpty(details.domain) ? "App: {0}, Tenant: {1}" : "App: {0}, Tenant: {1} ({2})", cacheItem.AppId, tenantId, details.domain);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
var subscriptions = details.subscriptions;
|
||||
yield return string.Format("\tThere are {0} subscriptions", subscriptions.Length);
|
||||
|
||||
foreach (var subscription in subscriptions)
|
||||
{
|
||||
yield return string.Format("\tSubscription {0} ({1})", subscription.subscriptionId, subscription.displayName);
|
||||
}
|
||||
yield return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
protected Task<AuthenticationResult> GetAuthorizationResult(Dictionary<TokenCacheKey, string> tokenCache, string tenantId, string user = null, string resource = Constants.CSMResource)
|
||||
protected async Task<TokenCacheInfo> GetAuthorizationResultByRefreshToken(CustomTokenCache tokenCache, TokenCacheInfo cacheInfo)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<AuthenticationResult>();
|
||||
var azureEnvironment = this.AzureEnvironments;
|
||||
var authority = String.Format("{0}/{1}", Constants.AADLoginUrls[(int)azureEnvironment], cacheInfo.TenantId);
|
||||
var context = new AuthenticationContext(
|
||||
authority: authority,
|
||||
validateAuthority: true,
|
||||
tokenCache: tokenCache);
|
||||
|
||||
AuthenticationResult result = await context.AcquireTokenByRefreshTokenAsync(
|
||||
refreshToken: cacheInfo.RefreshToken,
|
||||
clientId: Constants.AADClientId,
|
||||
resource: cacheInfo.Resource);
|
||||
|
||||
var ret = new TokenCacheInfo(cacheInfo.Resource, result);
|
||||
ret.TenantId = cacheInfo.TenantId;
|
||||
ret.DisplayableId = cacheInfo.DisplayableId;
|
||||
tokenCache.Add(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected Task<TokenCacheInfo> GetAuthorizationResult(CustomTokenCache tokenCache, string tenantId, string user = null, string resource = Constants.CSMResource)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<TokenCacheInfo>();
|
||||
|
||||
TokenCacheInfo found;
|
||||
if (tokenCache.TryGetValue(tenantId, resource, out found))
|
||||
{
|
||||
tcs.SetResult(found);
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
var thread = new Thread(() =>
|
||||
{
|
||||
try
|
||||
|
@ -291,7 +321,7 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
var context = new AuthenticationContext(
|
||||
authority: authority,
|
||||
validateAuthority: true,
|
||||
tokenCacheStore: tokenCache);
|
||||
tokenCache: tokenCache);
|
||||
|
||||
AuthenticationResult result = null;
|
||||
if (!string.IsNullOrEmpty(user))
|
||||
|
@ -299,8 +329,7 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
result = context.AcquireToken(
|
||||
resource: resource,
|
||||
clientId: Constants.AADClientId,
|
||||
redirectUri: new Uri(Constants.AADRedirectUri),
|
||||
userId: null);
|
||||
redirectUri: new Uri(Constants.AADRedirectUri));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -311,7 +340,9 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
promptBehavior: PromptBehavior.Always);
|
||||
}
|
||||
|
||||
tcs.TrySetResult(result);
|
||||
var cacheInfo = new TokenCacheInfo(resource, result);
|
||||
tokenCache.Add(cacheInfo);
|
||||
tcs.TrySetResult(cacheInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -326,28 +357,43 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
return tcs.Task;
|
||||
}
|
||||
|
||||
protected AuthenticationResult GetAuthorizationResultByAppKey(Dictionary<TokenCacheKey, string> tokenCache, string tenantId, string appId, string appKey, string resource = Constants.CSMResource)
|
||||
protected TokenCacheInfo GetAuthorizationResultBySpn(CustomTokenCache tokenCache, string tenantId, string appId, string appKey, string resource)
|
||||
{
|
||||
var azureEnvironment = this.AzureEnvironments;
|
||||
var authority = String.Format("{0}/{1}", Constants.AADLoginUrls[(int)azureEnvironment], tenantId);
|
||||
var context = new AuthenticationContext(
|
||||
authority: authority,
|
||||
validateAuthority: true,
|
||||
tokenCacheStore: tokenCache);
|
||||
tokenCache: tokenCache);
|
||||
var credential = new ClientCredential(appId, appKey);
|
||||
var authResult = context.AcquireToken(resource, credential);
|
||||
var result = context.AcquireToken(resource, credential);
|
||||
|
||||
// this will only get us one token, we save AppId and AppKey info in TokenCacheKey
|
||||
var key = tokenCache.Keys.First(k => String.Equals(k.Resource, resource, StringComparison.OrdinalIgnoreCase));
|
||||
SaveApplicationInfo(key, tenantId, appId, appKey);
|
||||
|
||||
return authResult;
|
||||
var cacheInfo = new TokenCacheInfo(tenantId, appId, appKey, resource, result);
|
||||
tokenCache.Add(cacheInfo);
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
protected async Task<Dictionary<string, TenantCacheInfo>> GetTokenForTenants(Dictionary<TokenCacheKey, string> tokenCache, AuthenticationResult authResult)
|
||||
protected TokenCacheInfo GetAuthorizationResultByUpn(CustomTokenCache tokenCache, string tenantId, string username, string password, string resource)
|
||||
{
|
||||
var tenantIds = await GetTenantIds(authResult);
|
||||
Trace.WriteLine(string.Format("User {0} belongs to {1} tenants", authResult.UserInfo.UserId, tenantIds.Length));
|
||||
var azureEnvironment = this.AzureEnvironments;
|
||||
var authority = String.Format("{0}/{1}", Constants.AADLoginUrls[(int)azureEnvironment], tenantId);
|
||||
var context = new AuthenticationContext(
|
||||
authority: authority,
|
||||
validateAuthority: true,
|
||||
tokenCache: tokenCache);
|
||||
var credential = new UserCredential(username, password);
|
||||
var result = context.AcquireToken(resource, Constants.AADClientId, credential);
|
||||
|
||||
var cacheInfo = new TokenCacheInfo(resource, result);
|
||||
tokenCache.Add(cacheInfo);
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
protected async Task<Dictionary<string, TenantCacheInfo>> GetTokenForTenants(CustomTokenCache tokenCache, TokenCacheInfo cacheInfo)
|
||||
{
|
||||
var recentInfo = cacheInfo;
|
||||
var tenantIds = await GetTenantIds(cacheInfo);
|
||||
Utils.Trace.WriteLine(string.Format("User {0} belongs to {1} tenants", cacheInfo.DisplayableId, tenantIds.Length));
|
||||
|
||||
var tenantCache = this.TenantStorage.GetCache();
|
||||
foreach (var tenantId in tenantIds)
|
||||
|
@ -359,35 +405,35 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
domain = "unknown"
|
||||
};
|
||||
|
||||
AuthenticationResult result = null;
|
||||
TokenCacheInfo result = null;
|
||||
try
|
||||
{
|
||||
result = await GetAuthorizationResult(tokenCache, tenantId: tenantId, user: authResult.UserInfo.UserId);
|
||||
result = await GetAuthorizationResult(tokenCache, tenantId: tenantId, user: cacheInfo.DisplayableId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(string.Format("User: {0}, Tenant: {1} {2}", authResult.UserInfo.UserId, tenantId, ex.Message));
|
||||
Trace.WriteLine(string.Empty);
|
||||
Utils.Trace.WriteLine(string.Format("User: {0}, Tenant: {1} {2}", cacheInfo.DisplayableId, tenantId, ex.Message));
|
||||
Utils.Trace.WriteLine(string.Empty);
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var aadToken = await GetAuthorizationResult(tokenCache, tenantId: tenantId, user: authResult.UserInfo.UserId, resource: Constants.AADGraphUrls[(int)AzureEnvironments]);
|
||||
var aadToken = await GetAuthorizationResult(tokenCache, tenantId: tenantId, user: cacheInfo.DisplayableId, resource: Constants.AADGraphUrls[(int)AzureEnvironments]);
|
||||
var details = await GetTenantDetail(aadToken, tenantId);
|
||||
info.displayName = details.displayName;
|
||||
info.domain = details.verifiedDomains.First(d => d.@default).name;
|
||||
Trace.WriteLine(string.Format("User: {0}, Tenant: {1} ({2})", result.UserInfo.UserId, tenantId, details.verifiedDomains.First(d => d.@default).name));
|
||||
Utils.Trace.WriteLine(string.Format("User: {0}, Tenant: {1} ({2})", result.DisplayableId, tenantId, details.verifiedDomains.First(d => d.@default).name));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(string.Format("User: {0}, Tenant: {1} {2}", result.UserInfo.UserId, tenantId, ex.Message));
|
||||
Utils.Trace.WriteLine(string.Format("User: {0}, Tenant: {1} {2}", result.DisplayableId, tenantId, ex.Message));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var subscriptions = await GetSubscriptions(result);
|
||||
Trace.WriteLine(string.Format("\tThere are {0} subscriptions", subscriptions.Length));
|
||||
Utils.Trace.WriteLine(string.Format("\tThere are {0} subscriptions", subscriptions.Length));
|
||||
|
||||
info.subscriptions = subscriptions.Select(subscription => new SubscriptionCacheInfo
|
||||
{
|
||||
|
@ -397,30 +443,32 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
|
||||
if (info.subscriptions.Length > 0)
|
||||
{
|
||||
this.TokenStorage.SaveRecentToken(result);
|
||||
recentInfo = result;
|
||||
}
|
||||
|
||||
foreach (var subscription in subscriptions)
|
||||
{
|
||||
Trace.WriteLine(string.Format("\tSubscription {0} ({1})", subscription.subscriptionId, subscription.displayName));
|
||||
Utils.Trace.WriteLine(string.Format("\tSubscription {0} ({1})", subscription.subscriptionId, subscription.displayName));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace.WriteLine(string.Format("\t{0}!", ex.Message));
|
||||
Utils.Trace.WriteLine(string.Format("\t{0}!", ex.Message));
|
||||
}
|
||||
tenantCache[tenantId] = info;
|
||||
Trace.WriteLine(string.Empty);
|
||||
Utils.Trace.WriteLine(string.Empty);
|
||||
}
|
||||
|
||||
this.TokenStorage.SaveRecentToken(recentInfo, Constants.CSMResource);
|
||||
|
||||
return tenantCache;
|
||||
}
|
||||
|
||||
private async Task<string[]> GetTenantIds(AuthenticationResult authResult)
|
||||
private async Task<string[]> GetTenantIds(TokenCacheInfo cacheInfo)
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("Authorization", authResult.CreateAuthorizationHeader());
|
||||
client.DefaultRequestHeaders.Add("Authorization", cacheInfo.CreateAuthorizationHeader());
|
||||
client.DefaultRequestHeaders.Add("User-Agent", Constants.UserAgent.Value);
|
||||
|
||||
var azureEnvironment = this.AzureEnvironments;
|
||||
|
@ -438,7 +486,7 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<TenantDetails> GetTenantDetail(AuthenticationResult authResult, string tenantId)
|
||||
private async Task<TenantDetails> GetTenantDetail(TokenCacheInfo cacheInfo, string tenantId)
|
||||
{
|
||||
if (Constants.InfrastructureTenantIds.Contains(tenantId))
|
||||
{
|
||||
|
@ -459,7 +507,7 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("Authorization", authResult.CreateAuthorizationHeader());
|
||||
client.DefaultRequestHeaders.Add("Authorization", cacheInfo.CreateAuthorizationHeader());
|
||||
client.DefaultRequestHeaders.Add("User-Agent", Constants.UserAgent.Value);
|
||||
|
||||
var azureEnvironment = this.AzureEnvironments;
|
||||
|
@ -487,11 +535,11 @@ namespace ARMClient.Authentication.AADAuthentication
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<SubscriptionInfo[]> GetSubscriptions(AuthenticationResult authResult)
|
||||
private async Task<SubscriptionInfo[]> GetSubscriptions(TokenCacheInfo cacheInfo)
|
||||
{
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("Authorization", authResult.CreateAuthorizationHeader());
|
||||
client.DefaultRequestHeaders.Add("Authorization", cacheInfo.CreateAuthorizationHeader());
|
||||
client.DefaultRequestHeaders.Add("User-Agent", Constants.UserAgent.Value);
|
||||
|
||||
var azureEnvironment = this.AzureEnvironments;
|
||||
|
|
|
@ -30,11 +30,13 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory">
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.1.0.5\lib\net40\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=2.14.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.14.201151115\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms">
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.1.0.5\lib\net40\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll</HintPath>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms, Version=2.14.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.14.201151115\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
@ -67,6 +69,8 @@
|
|||
<Compile Include="Contracts\TenantCacheInfo.cs" />
|
||||
<Compile Include="Contracts\TenantDetails.cs" />
|
||||
<Compile Include="Contracts\TenantInfo.cs" />
|
||||
<Compile Include="Contracts\CustomTokenCache.cs" />
|
||||
<Compile Include="Contracts\TokenCacheInfo.cs" />
|
||||
<Compile Include="Contracts\VerifiedDomain.cs" />
|
||||
<Compile Include="EnvironmentStorage\FileEnvironmentStorage.cs" />
|
||||
<Compile Include="EnvironmentStorage\IEnvironmentStorage.cs" />
|
||||
|
@ -80,6 +84,7 @@
|
|||
<Compile Include="TokenStorage\ITokenStorage.cs" />
|
||||
<Compile Include="TokenStorage\MemoryTokenStorage.cs" />
|
||||
<Compile Include="Utilities\ProtectedFile.cs" />
|
||||
<Compile Include="Utilities\Utils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace ARMClient.Authentication.Contracts
|
||||
{
|
||||
public class CustomTokenCache : TokenCache
|
||||
{
|
||||
private Dictionary<string, TokenCacheInfo> _caches;
|
||||
|
||||
public CustomTokenCache(string state = null)
|
||||
{
|
||||
if (state == null)
|
||||
{
|
||||
_caches = new Dictionary<string, TokenCacheInfo>();
|
||||
}
|
||||
else
|
||||
{
|
||||
_caches = JsonConvert.DeserializeObject<Dictionary<string, TokenCacheInfo>>(state);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<TokenCacheInfo> GetValues(string resource)
|
||||
{
|
||||
return _caches.Values.Where(c => c.Resource == resource);
|
||||
}
|
||||
|
||||
public string GetState()
|
||||
{
|
||||
return JObject.FromObject(_caches).ToString();
|
||||
}
|
||||
|
||||
public bool TryGetValue(string tenantId, string resource, out TokenCacheInfo cacheInfo)
|
||||
{
|
||||
return _caches.TryGetValue(GetKey(tenantId, resource), out cacheInfo);
|
||||
}
|
||||
|
||||
public TokenCacheInfo Get(string tenantId, string resource)
|
||||
{
|
||||
return _caches[GetKey(tenantId, resource)];
|
||||
}
|
||||
|
||||
public void Add(TokenCacheInfo cacheInfo)
|
||||
{
|
||||
_caches[GetKey(cacheInfo.TenantId, cacheInfo.Resource)] = cacheInfo;
|
||||
}
|
||||
|
||||
private string GetKey(string tenantId, string resource)
|
||||
{
|
||||
return String.Format("{0}::{1}", tenantId, resource);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
|
||||
namespace ARMClient.Authentication.Contracts
|
||||
{
|
||||
public class TokenCacheInfo
|
||||
{
|
||||
public TokenCacheInfo()
|
||||
{
|
||||
}
|
||||
|
||||
public TokenCacheInfo(string tenantId, string appId, string appKey, string resource, AuthenticationResult result)
|
||||
: this(resource, result)
|
||||
{
|
||||
AppId = appId;
|
||||
AppKey = appKey;
|
||||
TenantId = tenantId;
|
||||
}
|
||||
|
||||
public TokenCacheInfo(string resource, AuthenticationResult result)
|
||||
{
|
||||
AccessToken = result.AccessToken;
|
||||
DisplayableId = result.UserInfo == null ? null : result.UserInfo.DisplayableId;
|
||||
ExpiresOn = result.ExpiresOn;
|
||||
RefreshToken = result.RefreshToken;
|
||||
Resource = resource;
|
||||
TenantId = result.TenantId;
|
||||
}
|
||||
|
||||
public string AppId { get; set; }
|
||||
public string AppKey { get; set; }
|
||||
public string AccessToken { get; set; }
|
||||
public string DisplayableId { get; set; }
|
||||
public DateTimeOffset ExpiresOn { get; set; }
|
||||
public string RefreshToken { get; set; }
|
||||
public string Resource { get; set; }
|
||||
public string TenantId { get; set; }
|
||||
|
||||
public string CreateAuthorizationHeader()
|
||||
{
|
||||
return String.Format("Bearer {0}", AccessToken);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ARMClient.Authentication.Contracts;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
|
||||
namespace ARMClient.Authentication
|
||||
{
|
||||
|
@ -9,11 +9,9 @@ namespace ARMClient.Authentication
|
|||
{
|
||||
AzureEnvironments AzureEnvironments { get; set; }
|
||||
Task AcquireTokens();
|
||||
Task<AuthenticationResult> GetTokenByTenant(string tenantId);
|
||||
Task<AuthenticationResult> GetTokenBySubscription(string subscriptionId);
|
||||
Task<AuthenticationResult> GetTokenBySpn(string tenantId, string appId, string appKey);
|
||||
Task<AuthenticationResult> GetRecentToken();
|
||||
Task<string> GetAuthorizationHeader(string subscriptionId);
|
||||
Task<TokenCacheInfo> GetToken(string id, string resource);
|
||||
Task<TokenCacheInfo> GetTokenBySpn(string tenantId, string appId, string appKey);
|
||||
Task<TokenCacheInfo> GetTokenByUpn(string tenantId, string username, string password);
|
||||
bool IsCacheValid();
|
||||
void ClearTokenCache();
|
||||
IEnumerable<string> DumpTokenCache();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using ARMClient.Authentication.Contracts;
|
||||
using ARMClient.Authentication.Utilities;
|
||||
|
@ -32,14 +31,13 @@ namespace ARMClient.Authentication.TenantStorage
|
|||
|
||||
public bool IsCacheValid()
|
||||
{
|
||||
var cache = GetCache();
|
||||
return cache != null && cache.Count > 0;
|
||||
var file = ProtectedFile.GetCacheFile(_fileName);
|
||||
return File.Exists(file);
|
||||
}
|
||||
|
||||
public void ClearCache()
|
||||
{
|
||||
var filePath = ProtectedFile.GetCacheFile(_fileName);
|
||||
if (File.Exists(filePath))
|
||||
foreach (var filePath in Directory.GetFiles(Path.GetDirectoryName(ProtectedFile.GetCacheFile(_fileName)), "cache_tenants*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using ARMClient.Authentication.Contracts;
|
||||
using ARMClient.Authentication.Utilities;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
|
@ -13,47 +10,54 @@ namespace ARMClient.Authentication.TokenStorage
|
|||
internal class FileTokenStorage : ITokenStorage
|
||||
{
|
||||
private const string _cacheFileName = "cache_tokens.dat";
|
||||
private const string _recentFileName = "recent_token.dat";
|
||||
private const string _recentARMFileName = "recent_token_arm.dat";
|
||||
private const string _recentAADFileName = "recent_token_aad.dat";
|
||||
|
||||
public Dictionary<TokenCacheKey, string> GetCache()
|
||||
public CustomTokenCache GetCache()
|
||||
{
|
||||
var file = ProtectedFile.GetCacheFile(_cacheFileName);
|
||||
if (!File.Exists(file))
|
||||
{
|
||||
return new Dictionary<TokenCacheKey, string>();
|
||||
return new CustomTokenCache();
|
||||
}
|
||||
|
||||
var dict = JsonConvert.DeserializeObject<Dictionary<string, TokenCacheKey>>(ProtectedFile.ReadAllText(file));
|
||||
return dict.ToDictionary(p => p.Value, p => p.Key);
|
||||
var state = ProtectedFile.ReadAllText(file);
|
||||
return new CustomTokenCache(state);
|
||||
}
|
||||
|
||||
public void SaveCache(Dictionary<TokenCacheKey, string> tokens)
|
||||
public void SaveCache(CustomTokenCache cache)
|
||||
{
|
||||
var dict = tokens.ToDictionary(p => p.Value, p => p.Key);
|
||||
var json = JObject.FromObject(dict);
|
||||
ProtectedFile.WriteAllText(ProtectedFile.GetCacheFile(_cacheFileName), json.ToString());
|
||||
var state = cache.GetState();
|
||||
ProtectedFile.WriteAllText(ProtectedFile.GetCacheFile(_cacheFileName), state);
|
||||
}
|
||||
|
||||
public AuthenticationResult GetRecentToken()
|
||||
public TokenCacheInfo GetRecentToken(string resource)
|
||||
{
|
||||
return AuthenticationResult.Deserialize(ProtectedFile.ReadAllText(ProtectedFile.GetCacheFile(_recentFileName)));
|
||||
var file = ProtectedFile.GetCacheFile(resource == Constants.CSMResource ? _recentARMFileName : _recentAADFileName);
|
||||
if (!File.Exists(file))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<TokenCacheInfo>(ProtectedFile.ReadAllText(file));
|
||||
}
|
||||
|
||||
public void SaveRecentToken(AuthenticationResult authResult)
|
||||
public void SaveRecentToken(TokenCacheInfo cacheInfo, string resource)
|
||||
{
|
||||
ProtectedFile.WriteAllText(ProtectedFile.GetCacheFile(_recentFileName), authResult.Serialize());
|
||||
var file = ProtectedFile.GetCacheFile(resource == Constants.CSMResource ? _recentARMFileName : _recentAADFileName);
|
||||
var json = JObject.FromObject(cacheInfo);
|
||||
ProtectedFile.WriteAllText(ProtectedFile.GetCacheFile(file), json.ToString());
|
||||
}
|
||||
|
||||
public bool IsCacheValid()
|
||||
{
|
||||
var cache = GetCache();
|
||||
return cache != null && cache.Count > 0;
|
||||
var file = ProtectedFile.GetCacheFile(_cacheFileName);
|
||||
return File.Exists(file);
|
||||
}
|
||||
|
||||
public void ClearCache()
|
||||
{
|
||||
var filePaths = new[] { ProtectedFile.GetCacheFile(_cacheFileName), ProtectedFile.GetCacheFile(_recentFileName) };
|
||||
foreach (var filePath in filePaths.Where(File.Exists))
|
||||
foreach (var filePath in Directory.GetFiles(ProtectedFile.GetCachePath(), "*token*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
using System.Collections.Generic;
|
||||
using ARMClient.Authentication.Contracts;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
|
||||
namespace ARMClient.Authentication.TokenStorage
|
||||
{
|
||||
public interface ITokenStorage
|
||||
{
|
||||
Dictionary<TokenCacheKey, string> GetCache();
|
||||
void SaveCache(Dictionary<TokenCacheKey, string> tokens);
|
||||
AuthenticationResult GetRecentToken();
|
||||
void SaveRecentToken(AuthenticationResult authResult);
|
||||
CustomTokenCache GetCache();
|
||||
void SaveCache(CustomTokenCache tokenCache);
|
||||
|
||||
TokenCacheInfo GetRecentToken(string resource);
|
||||
void SaveRecentToken(TokenCacheInfo cacheInfo, string resource);
|
||||
|
||||
bool IsCacheValid();
|
||||
void ClearCache();
|
||||
}
|
||||
|
|
|
@ -1,31 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ARMClient.Authentication.Contracts;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
|
||||
namespace ARMClient.Authentication.TokenStorage
|
||||
{
|
||||
internal class MemoryTokenStorage : ITokenStorage
|
||||
{
|
||||
private Dictionary<TokenCacheKey, string> _cache;
|
||||
private AuthenticationResult _recentToken;
|
||||
public Dictionary<TokenCacheKey, string> GetCache()
|
||||
private CustomTokenCache _cache;
|
||||
private TokenCacheInfo _recentToken;
|
||||
public CustomTokenCache GetCache()
|
||||
{
|
||||
return this._cache ?? new Dictionary<TokenCacheKey, string>();
|
||||
return this._cache ?? new CustomTokenCache();
|
||||
}
|
||||
|
||||
public void SaveCache(Dictionary<TokenCacheKey, string> cache)
|
||||
public void SaveCache(CustomTokenCache cache)
|
||||
{
|
||||
this._cache = cache;
|
||||
}
|
||||
|
||||
public AuthenticationResult GetRecentToken()
|
||||
public TokenCacheInfo GetRecentToken(string resource)
|
||||
{
|
||||
return this._recentToken;
|
||||
}
|
||||
|
||||
public void SaveRecentToken(AuthenticationResult authResult)
|
||||
public void SaveRecentToken(TokenCacheInfo cacheInfo, string resource)
|
||||
{
|
||||
this._recentToken = authResult;
|
||||
this._recentToken = cacheInfo;
|
||||
}
|
||||
|
||||
public bool IsCacheValid()
|
||||
|
|
|
@ -7,9 +7,14 @@ namespace ARMClient.Authentication.Utilities
|
|||
{
|
||||
internal static class ProtectedFile
|
||||
{
|
||||
public static string GetCachePath()
|
||||
{
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".arm");
|
||||
}
|
||||
|
||||
public static string GetCacheFile(string file)
|
||||
{
|
||||
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".arm");
|
||||
var path = GetCachePath();
|
||||
Directory.CreateDirectory(path);
|
||||
return Path.Combine(path, file);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ARMClient.Authentication.Utilities
|
||||
{
|
||||
public static class Utils
|
||||
{
|
||||
static TraceListener _traceListener;
|
||||
|
||||
public static TraceListener Trace
|
||||
{
|
||||
get { return _traceListener ?? DefaultTraceListener.Default; }
|
||||
}
|
||||
|
||||
public static void SetTraceListener(TraceListener listener)
|
||||
{
|
||||
_traceListener = listener;
|
||||
}
|
||||
|
||||
class DefaultTraceListener : TraceListener
|
||||
{
|
||||
public readonly static TraceListener Default = new DefaultTraceListener();
|
||||
|
||||
public override void Write(string message)
|
||||
{
|
||||
System.Diagnostics.Trace.Write(message);
|
||||
}
|
||||
|
||||
public override void WriteLine(string message)
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net451" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="1.0.5" targetFramework="net451" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="2.14.201151115" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net451" />
|
||||
</packages>
|
|
@ -33,11 +33,12 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory">
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.1.0.5\lib\net40\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=2.14.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.14.201151115\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms">
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.1.0.5\lib\net40\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll</HintPath>
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.14.201151115\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ARMClient
|
||||
{
|
||||
|
|
|
@ -35,6 +35,9 @@ namespace ARMClient
|
|||
{
|
||||
Console.ForegroundColor = headerNameColor;
|
||||
Console.WriteLine("{0} {1} HTTP/{2}", request.Method, request.RequestUri.PathAndQuery, request.Version);
|
||||
Console.Write("Host: ");
|
||||
Console.ForegroundColor = headerValueColor;
|
||||
Console.WriteLine(request.RequestUri.Host);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -11,7 +10,7 @@ using System.Windows.Forms;
|
|||
using ARMClient.Authentication;
|
||||
using ARMClient.Authentication.AADAuthentication;
|
||||
using ARMClient.Authentication.Contracts;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
using ARMClient.Authentication.Utilities;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace ARMClient
|
||||
|
@ -21,7 +20,7 @@ namespace ARMClient
|
|||
[STAThread]
|
||||
static int Main(string[] args)
|
||||
{
|
||||
Trace.Listeners.Add(new ConsoleTraceListener());
|
||||
Utils.SetTraceListener(new ConsoleTraceListener());
|
||||
try
|
||||
{
|
||||
var persistentAuthHelper = new PersistentAuthHelper();
|
||||
|
@ -65,20 +64,15 @@ namespace ARMClient
|
|||
|
||||
EnsureTokenCache(persistentAuthHelper);
|
||||
|
||||
AuthenticationResult authResult;
|
||||
if (tenantId != null)
|
||||
{
|
||||
EnsureGuidFormat(tenantId);
|
||||
authResult = persistentAuthHelper.GetTokenByTenant(tenantId).Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
authResult = persistentAuthHelper.GetRecentToken().Result;
|
||||
}
|
||||
|
||||
var bearer = authResult.CreateAuthorizationHeader();
|
||||
TokenCacheInfo cacheInfo = persistentAuthHelper.GetToken(tenantId, Constants.CSMResource).Result;
|
||||
var bearer = cacheInfo.CreateAuthorizationHeader();
|
||||
Clipboard.SetText(bearer);
|
||||
DumpClaims(authResult.AccessToken);
|
||||
DumpClaims(cacheInfo.AccessToken);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Token copied to clipboard successfully.");
|
||||
return 0;
|
||||
|
@ -91,13 +85,33 @@ namespace ARMClient
|
|||
var appId = _parameters.Get(2, keyName: "appId");
|
||||
EnsureGuidFormat(appId);
|
||||
|
||||
var appKey = _parameters.Get(3, keyName: "appKey");
|
||||
var env = _parameters.Get(1, requires: false);
|
||||
var appKey = _parameters.Get(3, keyName: "appKey", requires: false);
|
||||
if (appKey == null)
|
||||
{
|
||||
appKey = PromptForPassword("appKey");
|
||||
}
|
||||
_parameters.ThrowIfUnknown();
|
||||
|
||||
persistentAuthHelper.AzureEnvironments = env == null ? AzureEnvironments.Prod :
|
||||
(AzureEnvironments)Enum.Parse(typeof(AzureEnvironments), args[1], ignoreCase: true);
|
||||
var authResult = persistentAuthHelper.GetTokenBySpn(tenantId, appId, appKey).Result;
|
||||
persistentAuthHelper.AzureEnvironments = AzureEnvironments.Prod;
|
||||
var cacheInfo = persistentAuthHelper.GetTokenBySpn(tenantId, appId, appKey).Result;
|
||||
return 0;
|
||||
}
|
||||
else if (String.Equals(verb, "upn", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var tenantId = _parameters.Get(1, keyName: "tenant");
|
||||
EnsureGuidFormat(tenantId);
|
||||
|
||||
var username = _parameters.Get(2, keyName: "username");
|
||||
|
||||
var password = _parameters.Get(3, keyName: "password", requires: false);
|
||||
if (password == null)
|
||||
{
|
||||
password = PromptForPassword("password");
|
||||
}
|
||||
_parameters.ThrowIfUnknown();
|
||||
|
||||
persistentAuthHelper.AzureEnvironments = AzureEnvironments.Prod;
|
||||
var cacheInfo = persistentAuthHelper.GetTokenByUpn(tenantId, username, password).Result;
|
||||
return 0;
|
||||
}
|
||||
else if (String.Equals(verb, "get", StringComparison.OrdinalIgnoreCase)
|
||||
|
@ -107,38 +121,24 @@ namespace ARMClient
|
|||
{
|
||||
var path = _parameters.Get(1, keyName: "url");
|
||||
var verbose = _parameters.Get("-verbose", requires: false) != null;
|
||||
var baseUri = new Uri(ARMClient.Authentication.Constants.CSMUrls[(int)AzureEnvironments.Prod]);
|
||||
var uri = new Uri(baseUri, path);
|
||||
|
||||
if (!verbose)
|
||||
{
|
||||
Trace.Listeners.Clear();
|
||||
}
|
||||
|
||||
var uri = EnsureAbsoluteUri(path, persistentAuthHelper);
|
||||
if (!persistentAuthHelper.IsCacheValid())
|
||||
{
|
||||
persistentAuthHelper.AzureEnvironments = GetAzureEnvironments(uri);
|
||||
persistentAuthHelper.AcquireTokens().Wait();
|
||||
}
|
||||
|
||||
var env = persistentAuthHelper.AzureEnvironments;
|
||||
baseUri = new Uri(ARMClient.Authentication.Constants.CSMUrls[(int)env]);
|
||||
uri = new Uri(baseUri, path);
|
||||
var content = ParseHttpContent(verb, _parameters);
|
||||
_parameters.ThrowIfUnknown();
|
||||
|
||||
var subscriptionId = GetSubscription(uri);
|
||||
AuthenticationResult authResult;
|
||||
if (String.IsNullOrEmpty(subscriptionId))
|
||||
{
|
||||
authResult = persistentAuthHelper.GetRecentToken().Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
authResult = persistentAuthHelper.GetTokenBySubscription(subscriptionId).Result;
|
||||
}
|
||||
|
||||
return HttpInvoke(uri, authResult, verb, verbose, content).Result;
|
||||
var subscriptionId = GetTenantOrSubscription(uri);
|
||||
TokenCacheInfo cacheInfo = persistentAuthHelper.GetToken(subscriptionId, null).Result;
|
||||
return HttpInvoke(uri, cacheInfo, verb, verbose, content).Result;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -156,6 +156,68 @@ namespace ARMClient
|
|||
}
|
||||
}
|
||||
|
||||
static string PromptForPassword(string title)
|
||||
{
|
||||
string pass = "";
|
||||
Console.Write("Enter {0}: ", title);
|
||||
ConsoleKeyInfo key;
|
||||
|
||||
do
|
||||
{
|
||||
key = Console.ReadKey(true);
|
||||
|
||||
// Backspace Should Not Work
|
||||
if (key.Key != ConsoleKey.Backspace)
|
||||
{
|
||||
pass += key.KeyChar;
|
||||
Console.Write("*");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass = pass.Remove(pass.Length - 1);
|
||||
Console.Write("\b \b");
|
||||
}
|
||||
}
|
||||
// Stops Receving Keys Once Enter is Pressed
|
||||
while (key.Key != ConsoleKey.Enter);
|
||||
|
||||
pass = pass.Remove(pass.Length - 1);
|
||||
Console.Write("\b \b");
|
||||
Console.WriteLine("--" + pass + "--");
|
||||
|
||||
return pass;
|
||||
}
|
||||
|
||||
static Uri EnsureAbsoluteUri(string path, PersistentAuthHelper persistentAuthHelper)
|
||||
{
|
||||
Uri ret;
|
||||
if (Uri.TryCreate(path, UriKind.Absolute, out ret))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
var env = persistentAuthHelper.IsCacheValid() ? persistentAuthHelper.AzureEnvironments : AzureEnvironments.Prod;
|
||||
var parts = path.Split(new[] { '/', '?' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length <= 0
|
||||
|| String.Equals(parts[0], "tenants", StringComparison.OrdinalIgnoreCase)
|
||||
|| String.Equals(parts[0], "subscriptions", StringComparison.OrdinalIgnoreCase)
|
||||
|| String.Equals(parts[0], "providers", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new Uri(new Uri(ARMClient.Authentication.Constants.CSMUrls[(int)env]), path);
|
||||
}
|
||||
|
||||
Guid guid;
|
||||
if (Guid.TryParse(parts[0], out guid))
|
||||
{
|
||||
if (path.Length > 1 && String.Equals(parts[1], "services", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new Uri(new Uri(ARMClient.Authentication.Constants.RdfeUrls[(int)env]), path);
|
||||
}
|
||||
}
|
||||
|
||||
return new Uri(new Uri(ARMClient.Authentication.Constants.AADGraphUrls[(int)env]), path);
|
||||
}
|
||||
|
||||
static void EnsureGuidFormat(string parameter)
|
||||
{
|
||||
Guid result;
|
||||
|
@ -223,7 +285,11 @@ namespace ARMClient
|
|||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Get token by ServicePrincipalName");
|
||||
Console.WriteLine(" ARMClient.exe spn [tenant] [appId] [appKey]");
|
||||
Console.WriteLine(" ARMClient.exe spn [tenant] [appId] (appKey)");
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Get token by ServicePrincipalName");
|
||||
Console.WriteLine(" ARMClient.exe upn [tenant] [username] (password)");
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("List token cache");
|
||||
|
@ -263,11 +329,11 @@ namespace ARMClient
|
|||
return null;
|
||||
}
|
||||
|
||||
static async Task<int> HttpInvoke(Uri uri, AuthenticationResult authResult, string verb, bool verbose, HttpContent content)
|
||||
static async Task<int> HttpInvoke(Uri uri, TokenCacheInfo cacheInfo, string verb, bool verbose, HttpContent content)
|
||||
{
|
||||
using (var client = new HttpClient(new HttpLoggingHandler(new HttpClientHandler(), verbose)))
|
||||
{
|
||||
client.DefaultRequestHeaders.Add("Authorization", authResult.CreateAuthorizationHeader());
|
||||
client.DefaultRequestHeaders.Add("Authorization", cacheInfo.CreateAuthorizationHeader());
|
||||
client.DefaultRequestHeaders.Add("User-Agent", Constants.UserAgent.Value);
|
||||
client.DefaultRequestHeaders.Add("Accept", Constants.JsonContentType);
|
||||
|
||||
|
@ -276,6 +342,8 @@ namespace ARMClient
|
|||
client.DefaultRequestHeaders.Add("x-ms-version", "2013-10-01");
|
||||
}
|
||||
|
||||
client.DefaultRequestHeaders.Add("x-ms-request-id", Guid.NewGuid().ToString());
|
||||
|
||||
HttpResponseMessage response = null;
|
||||
if (String.Equals(verb, "get", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
@ -374,17 +442,17 @@ namespace ARMClient
|
|||
return Constants.AADGraphUrls.Any(url => url.IndexOf(host, StringComparison.OrdinalIgnoreCase) > 0);
|
||||
}
|
||||
|
||||
static string GetSubscription(Uri uri)
|
||||
static string GetTenantOrSubscription(Uri uri)
|
||||
{
|
||||
try
|
||||
{
|
||||
var paths = uri.AbsolutePath.Split(new[] { '/', '?' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (IsGraphApi(uri))
|
||||
{
|
||||
return null;
|
||||
return Guid.Parse(paths[0]).ToString();
|
||||
}
|
||||
|
||||
var paths = uri.AbsolutePath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (paths.Length >= 2 && paths[0] == "subscriptions")
|
||||
if (paths.Length >= 2 && String.Equals(paths[0], "subscriptions", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return Guid.Parse(paths[1]).ToString();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net451" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="1.0.5" targetFramework="net451" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="2.14.201151115" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net451" />
|
||||
</packages>
|
|
@ -33,12 +33,13 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=2.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=2.14.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.1.0.5\lib\net40\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.14.201151115\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms">
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.1.0.5\lib\net40\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll</HintPath>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms, Version=2.14.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.2.14.201151115\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net451" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="1.0.5" targetFramework="net451" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="2.14.201151115" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net451" />
|
||||
</packages>
|
|
@ -17,7 +17,7 @@ namespace ARMClient.Library
|
|||
{
|
||||
public class ARMClient : DynamicObject
|
||||
{
|
||||
private string _url = "https://management.azure.com";
|
||||
private string _url = null;
|
||||
private string _authorizationHeader;
|
||||
private readonly string _apiVersion;
|
||||
private readonly IAuthHelper _authHelper;
|
||||
|
@ -29,24 +29,19 @@ namespace ARMClient.Library
|
|||
return new ARMClient(apiVersion, authHelper, azureEnvironment, url);
|
||||
}
|
||||
|
||||
public static dynamic GetDynamicClient(string apiVersion, string authorizationHeader, string url = null)
|
||||
{
|
||||
return new ARMClient(apiVersion, authorizationHeader, url);
|
||||
}
|
||||
|
||||
private ARMClient(string apiVersion, IAuthHelper authHelper = null,
|
||||
AzureEnvironments azureEnvironment = AzureEnvironments.Prod, string url = null)
|
||||
{
|
||||
this._apiVersion = apiVersion;
|
||||
this._authHelper = authHelper ?? new AuthHelper(azureEnvironment);
|
||||
this._azureEnvironment = azureEnvironment;
|
||||
this._url = url ?? "https://management.azure.com";
|
||||
this._url = url ?? Constants.CSMUrls[(int)azureEnvironment];
|
||||
}
|
||||
|
||||
private ARMClient(string apiVersion, string authorizationHeader, string url = null)
|
||||
private ARMClient(string apiVersion, string authorizationHeader, string url)
|
||||
{
|
||||
this._authorizationHeader = authorizationHeader;
|
||||
this._url = url ?? "https://management.azure.com";
|
||||
this._url = url;
|
||||
}
|
||||
|
||||
public async Task InitializeToken(string subscriptionId = null)
|
||||
|
@ -62,7 +57,8 @@ namespace ARMClient.Library
|
|||
await this._authHelper.AcquireTokens().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
this._authorizationHeader = await this._authHelper.GetAuthorizationHeader(subscriptionId).ConfigureAwait(false);
|
||||
TokenCacheInfo cacheInfo = await this._authHelper.GetToken(subscriptionId, Constants.CSMResource).ConfigureAwait(false);
|
||||
this._authorizationHeader = cacheInfo.CreateAuthorizationHeader();
|
||||
}
|
||||
|
||||
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||
|
@ -157,8 +153,8 @@ namespace ARMClient.Library
|
|||
|
||||
private Task<HttpResponseMessage> HttpInvoke(string httpVerb, object[] args)
|
||||
{
|
||||
this._url = string.Format("{0}?api-version={1}", this._url, this._apiVersion);
|
||||
return HttpInvoke(new Uri(this._url), httpVerb, args.Length > 0 ? args[0].ToString() : string.Empty);
|
||||
var uri = string.Format("{0}?api-version={1}", this._url, this._apiVersion);
|
||||
return HttpInvoke(new Uri(uri), httpVerb, args.Length > 0 ? args[0].ToString() : string.Empty);
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> HttpInvoke(Uri uri, string verb, string payload)
|
||||
|
@ -168,6 +164,7 @@ namespace ARMClient.Library
|
|||
client.DefaultRequestHeaders.Add("Authorization", this._authorizationHeader);
|
||||
client.DefaultRequestHeaders.Add("User-Agent", Constants.UserAgent.Value);
|
||||
client.DefaultRequestHeaders.Add("Accept", Constants.JsonContentType);
|
||||
client.DefaultRequestHeaders.Add("x-ms-request-id", Guid.NewGuid().ToString());
|
||||
|
||||
HttpResponseMessage response = null;
|
||||
if (String.Equals(verb, "get", StringComparison.OrdinalIgnoreCase))
|
||||
|
|
Загрузка…
Ссылка в новой задаче