public void SaveRecentToken(TokenCacheInfo cacheInfo, string resource) { var file = ProtectedFile.GetCacheFile(GetRecentTokenFileName(resource)); var json = JObject.FromObject(cacheInfo); ProtectedFile.WriteAllText(ProtectedFile.GetCacheFile(file), json.ToString()); }
public bool TryGetValue(string tenantId, string resource, out TokenCacheInfo cacheInfo) { return _caches.TryGetValue(GetKey(tenantId, resource), out cacheInfo); }
private async Task<TenantDetails> GetTenantDetail(TokenCacheInfo cacheInfo, string tenantId) { if (Constants.InfrastructureTenantIds.Contains(tenantId)) { return new TenantDetails { objectId = tenantId, displayName = "Infrastructure", verifiedDomains = new[] { new VerifiedDomain { name = "live.com", @default = true } } }; } using (var client = new HttpClient()) { client.DefaultRequestHeaders.Add("Authorization", cacheInfo.CreateAuthorizationHeader()); client.DefaultRequestHeaders.Add("User-Agent", Constants.UserAgent.Value); var azureEnvironment = this.AzureEnvironments; var url = string.Format("{0}/{1}/tenantDetails?api-version={2}", Constants.AADGraphUrls[(int)azureEnvironment], tenantId, Constants.AADGraphApiVersion); using (var response = await client.GetAsync(url)) { if (response.IsSuccessStatusCode) { var result = await response.Content.ReadAsAsync<ResultOf<TenantDetails>>(); return result.value[0]; } var content = await response.Content.ReadAsStringAsync(); if (content.StartsWith("{")) { var error = (JObject)JObject.Parse(content)["odata.error"]; if (error != null) { throw new InvalidOperationException(String.Format("GetTenantDetail {0}, {1}", response.StatusCode, error["message"].Value<string>("value"))); } } throw new InvalidOperationException(String.Format("GetTenantDetail {0}, {1}", response.StatusCode, await response.Content.ReadAsStringAsync())); } } }
private async Task<SubscriptionInfo[]> GetSubscriptions(TokenCacheInfo cacheInfo) { using (var client = new HttpClient()) { client.DefaultRequestHeaders.Add("Authorization", cacheInfo.CreateAuthorizationHeader()); client.DefaultRequestHeaders.Add("User-Agent", Constants.UserAgent.Value); var azureEnvironment = this.AzureEnvironments; var url = string.Format("{0}/subscriptions?api-version={1}", Constants.CSMUrls[(int)azureEnvironment], Constants.CSMApiVersion); using (var response = await client.GetAsync(url)) { if (response.IsSuccessStatusCode) { var result = await response.Content.ReadAsAsync<ResultOf<SubscriptionInfo>>(); return result.value; } var content = await response.Content.ReadAsStringAsync(); if (content.StartsWith("{")) { var error = (JObject)JObject.Parse(content)["error"]; if (error != null) { throw new InvalidOperationException(String.Format("GetSubscriptions {0}, {1}", response.StatusCode, error.Value<string>("message"))); } } throw new InvalidOperationException(String.Format("GetSubscriptions {0}, {1}", response.StatusCode, await response.Content.ReadAsStringAsync())); } } }
protected async Task<Dictionary<string, TenantCacheInfo>> GetTokenForTenants(CustomTokenCache tokenCache, TokenCacheInfo cacheInfo, string appId = null, string appKey = null, string username = null, string password = null) { var recentInfo = cacheInfo; var tenantIds = await GetTenantIds(cacheInfo); if (!tenantIds.Contains(cacheInfo.TenantId)) { var list = tenantIds.ToList(); list.Insert(0, cacheInfo.TenantId); tenantIds = list.ToArray(); } var tenantCache = this.TenantStorage.GetCache(); foreach (var tenantId in tenantIds) { var info = new TenantCacheInfo { tenantId = tenantId, displayName = "unknown", domain = (tenantIds.Length == 1 || tenantId != cacheInfo.TenantId) ? cacheInfo.TenantId : "unknown" }; TokenCacheInfo result = null; try { if (!String.IsNullOrEmpty(appId) && !String.IsNullOrEmpty(appKey)) { result = GetAuthorizationResultBySpn(tokenCache, tenantId: tenantId, appId: appId, appKey: appKey, resource: Constants.CSMResources[(int)AzureEnvironments]); } else if (!String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password)) { result = GetAuthorizationResultByUpn(tokenCache, tenantId: tenantId, username: username, password: password, resource: Constants.CSMResources[(int)AzureEnvironments]); } else { result = await GetAuthorizationResult(tokenCache, tenantId: tenantId, user: cacheInfo.DisplayableId); } } catch (Exception ex) { Utils.Trace.WriteLine(string.Format("User: {0}, Tenant: {1} {2}", cacheInfo.DisplayableId, tenantId, ex.Message)); Utils.Trace.WriteLine(string.Empty); continue; } try { TokenCacheInfo aadToken = null; if (!String.IsNullOrEmpty(appId) && appKey == "_certificate_") { Utils.Trace.WriteLine(string.Format("AppId: {0}, Tenant: {1}", appId, tenantId)); } else if (!String.IsNullOrEmpty(appId) && !String.IsNullOrEmpty(appKey)) { aadToken = GetAuthorizationResultBySpn(tokenCache, tenantId: tenantId, appId: appId, appKey: appKey, resource: Constants.AADGraphUrls[(int)AzureEnvironments]); } else if (!String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password)) { aadToken = GetAuthorizationResultByUpn(tokenCache, tenantId: tenantId, username: username, password: password, resource: Constants.AADGraphUrls[(int)AzureEnvironments]); } else { aadToken = await GetAuthorizationResult(tokenCache, tenantId: tenantId, user: cacheInfo.DisplayableId, resource: Constants.AADGraphUrls[(int)AzureEnvironments]); } if (aadToken != null) { var details = await GetTenantDetail(aadToken, tenantId); info.displayName = details.displayName; info.domain = details.verifiedDomains.First(d => d.@default).name; if (!String.IsNullOrEmpty(appId) && !String.IsNullOrEmpty(appKey)) { Utils.Trace.WriteLine(string.Format("AppId: {0}, Tenant: {1} ({2})", appId, tenantId, info.domain)); } else { Utils.Trace.WriteLine(string.Format("User: {0}, Tenant: {1} ({2})", result.DisplayableId, tenantId, info.domain)); } } } catch (Exception) { if (!String.IsNullOrEmpty(appId) && !String.IsNullOrEmpty(appKey)) { Utils.Trace.WriteLine(string.Format("AppId: {0}, Tenant: {1}", appId, tenantId)); } else { Utils.Trace.WriteLine(string.Format("User: {0}, Tenant: {1}", result.DisplayableId, tenantId)); } } try { var subscriptions = await GetSubscriptions(result); 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(); if (recentInfo != null && info.subscriptions.Length > 0) { recentInfo = result; } foreach (var subscription in subscriptions) { Utils.Trace.WriteLine(string.Format("\tSubscription {0} ({1})", subscription.subscriptionId, subscription.displayName)); } } catch (Exception ex) { Utils.Trace.WriteLine(string.Format("\t{0}!", ex.Message)); } tenantCache[tenantId] = info; if (!String.IsNullOrEmpty(info.domain) && info.domain != "unknown") { tenantCache[info.domain] = info; } Utils.Trace.WriteLine(string.Empty); } this.TokenStorage.SaveRecentToken(recentInfo, Constants.CSMResources[(int)AzureEnvironments]); return tenantCache; }
public bool TryGetValue(string tenantId, string resource, out TokenCacheInfo cacheInfo) { return(_caches.TryGetValue(GetKey(tenantId, resource), out cacheInfo)); }
protected TokenCacheInfo GetAuthorizationResultBySpn(CustomTokenCache tokenCache, string tenantId, string appId, X509Certificate2 certificate, string resource) { TokenCacheInfo found; if (tokenCache.TryGetValue(tenantId, resource, out found)) { return found; } 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 ClientAssertionCertificate(appId, certificate); var result = context.AcquireToken(resource, credential); var cacheInfo = new TokenCacheInfo(tenantId, appId, "_certificate_", resource, result); tokenCache.Add(cacheInfo); return cacheInfo; }
public static async Task<JObject> HttpGet(Uri uri, TokenCacheInfo cacheInfo) { using (var client = new HttpClient()) { client.DefaultRequestHeaders.Add("Authorization", cacheInfo.CreateAuthorizationHeader()); client.DefaultRequestHeaders.Add("User-Agent", Constants.UserAgent.Value); client.DefaultRequestHeaders.Add("Accept", Constants.JsonContentType); if (Utils.IsRdfe(uri)) { client.DefaultRequestHeaders.Add("x-ms-version", "2013-10-01"); } client.DefaultRequestHeaders.Add("x-ms-request-id", Guid.NewGuid().ToString()); using (var response = await client.GetAsync(uri)) { var content = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { Trace.WriteLine("Status: " + response.StatusCode); Trace.WriteLine("Content: " + content); } response.EnsureSuccessStatusCode(); return JObject.Parse(content); } } }
protected async Task<TokenCacheInfo> GetAuthorizationResultByRefreshToken(CustomTokenCache tokenCache, TokenCacheInfo cacheInfo) { 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 = null) { var tcs = new TaskCompletionSource<TokenCacheInfo>(); resource = resource ?? Constants.CSMResources[(int)AzureEnvironments]; TokenCacheInfo found; if (tokenCache.TryGetValue(tenantId, resource, out found)) { tcs.SetResult(found); return tcs.Task; } var thread = new Thread(() => { try { 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); AuthenticationResult result = null; if (!string.IsNullOrEmpty(user)) { result = context.AcquireToken( resource: resource, clientId: Constants.AADClientId, redirectUri: new Uri(Constants.AADRedirectUri), promptBehavior: PromptBehavior.Never, userId: new UserIdentifier(user, UserIdentifierType.OptionalDisplayableId)); } else { result = context.AcquireToken( resource: resource, clientId: Constants.AADClientId, redirectUri: new Uri(Constants.AADRedirectUri), promptBehavior: PromptBehavior.Always); } var cacheInfo = new TokenCacheInfo(resource, result); tokenCache.Add(cacheInfo); tcs.TrySetResult(cacheInfo); } catch (Exception ex) { tcs.TrySetException(ex); } }); thread.SetApartmentState(ApartmentState.STA); thread.Name = "AcquireTokenThread"; thread.Start(); return tcs.Task; }
protected async Task<TokenCacheInfo> RefreshToken(CustomTokenCache tokenCache, TokenCacheInfo cacheInfo) { if (!String.IsNullOrEmpty(cacheInfo.RefreshToken)) { try { return await GetAuthorizationResultByRefreshToken(tokenCache, cacheInfo); } catch (AdalServiceException ex) { if (ex.Message.IndexOf("The provided access grant is expired or revoked") > 0) { AcquireTokens().Wait(); cacheInfo = GetToken(cacheInfo.TenantId).Result; tokenCache.Clone(this.TokenStorage.GetCache()); return cacheInfo; } throw; } } else if (!String.IsNullOrEmpty(cacheInfo.AppId) && cacheInfo.AppKey == "_certificate_") { throw new InvalidOperationException("Unable to refresh expired token! Try login with certificate again."); } else if (!String.IsNullOrEmpty(cacheInfo.AppId) && !String.IsNullOrEmpty(cacheInfo.AppKey)) { return GetAuthorizationResultBySpn(tokenCache, cacheInfo.TenantId, cacheInfo.AppId, cacheInfo.AppKey, cacheInfo.Resource); } throw new NotImplementedException(); }
protected async Task<TokenCacheInfo> RefreshToken(CustomTokenCache tokenCache, TokenCacheInfo cacheInfo) { if (!String.IsNullOrEmpty(cacheInfo.RefreshToken)) { return await GetAuthorizationResultByRefreshToken(tokenCache, cacheInfo); } else if (!String.IsNullOrEmpty(cacheInfo.AppId) && cacheInfo.AppKey == "_certificate_") { throw new InvalidOperationException("Unable to refresh expired token! Try login with certificate again."); } else if (!String.IsNullOrEmpty(cacheInfo.AppId) && !String.IsNullOrEmpty(cacheInfo.AppKey)) { return GetAuthorizationResultBySpn(tokenCache, cacheInfo.TenantId, cacheInfo.AppId, cacheInfo.AppKey, cacheInfo.Resource); } throw new NotImplementedException(); }
public void Add(TokenCacheInfo cacheInfo) { _caches[GetKey(cacheInfo.TenantId, cacheInfo.Resource)] = cacheInfo; }
protected TokenCacheInfo GetAuthorizationResultByUpn(CustomTokenCache tokenCache, string tenantId, string username, string password, string resource) { TokenCacheInfo found; if (tokenCache.TryGetValue(tenantId, resource, out found)) { return found; } 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; }
public void SaveRecentToken(TokenCacheInfo cacheInfo, string resource) { var file = ProtectedFile.GetCacheFile(resource == Constants.CSMResource ? _recentARMFileName : _recentAADFileName); var json = JObject.FromObject(cacheInfo); ProtectedFile.WriteAllText(ProtectedFile.GetCacheFile(file), json.ToString()); }
private async Task<string[]> GetTenantIds(TokenCacheInfo cacheInfo) { using (var client = new HttpClient()) { client.DefaultRequestHeaders.Add("Authorization", cacheInfo.CreateAuthorizationHeader()); client.DefaultRequestHeaders.Add("User-Agent", Constants.UserAgent.Value); var azureEnvironment = this.AzureEnvironments; var url = string.Format("{0}/tenants?api-version={1}", Constants.CSMUrls[(int)azureEnvironment], Constants.CSMApiVersion); using (var response = await client.GetAsync(url)) { if (response.IsSuccessStatusCode) { var result = await response.Content.ReadAsAsync<ResultOf<TenantInfo>>(); return result.value.Select(tenant => tenant.tenantId).ToArray(); } throw new InvalidOperationException(await response.Content.ReadAsStringAsync()); } } }
static async Task<int> HttpInvoke(Uri uri, TokenCacheInfo cacheInfo, string verb, bool verbose, HttpContent content) { var logginerHandler = new HttpLoggingHandler(new HttpClientHandler(), verbose); return await Utils.HttpInvoke(uri, cacheInfo, verb, logginerHandler, content); }
public void SaveRecentToken(TokenCacheInfo cacheInfo, string resource) { this._recentToken = cacheInfo; }
public static async Task<int> HttpInvoke(Uri uri, TokenCacheInfo cacheInfo, string verb, DelegatingHandler handler, HttpContent content) { using (var client = new HttpClient(handler)) { client.DefaultRequestHeaders.Add("Authorization", cacheInfo.CreateAuthorizationHeader()); client.DefaultRequestHeaders.Add("User-Agent", Constants.UserAgent.Value); client.DefaultRequestHeaders.Add("Accept", Constants.JsonContentType); if (Utils.IsRdfe(uri)) { 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)) { response = await client.GetAsync(uri); } else if (String.Equals(verb, "delete", StringComparison.OrdinalIgnoreCase)) { response = await client.DeleteAsync(uri); } else if (String.Equals(verb, "post", StringComparison.OrdinalIgnoreCase)) { response = await client.PostAsync(uri, content); } else if (String.Equals(verb, "put", StringComparison.OrdinalIgnoreCase)) { response = await client.PutAsync(uri, content); } else if (String.Equals(verb, "patch", StringComparison.OrdinalIgnoreCase)) { using (var message = new HttpRequestMessage(new HttpMethod("PATCH"), uri)) { message.Content = content; response = await client.SendAsync(message).ConfigureAwait(false); } } else { throw new InvalidOperationException(String.Format("Invalid http verb {0}!", verb)); } using (response) { if (response.IsSuccessStatusCode) { return 0; } return (-1) * (int)response.StatusCode; } } }