public static async Task <string> GetAccessTokenAsync(int accountId) { string accessToken = null; await DataAccess.ExecuteTransactionAsync(async (cnn, trn) => { using (SqlCommand cmd = new SqlCommand() { CommandType = CommandType.Text, CommandText = "select top 1 * from AzureAccount with(updlock,rowlock) where AccountId=@accountId", Connection = cnn, Transaction = trn, }) { cmd.Parameters.AddWithValue("@accountId", accountId); DateTime?expiresOn = null; string clientId = null, clientSecret = null, user = null, password = null, tenantId = null; Models.AzureResources resource = Models.AzureResources.AzureResource_PowerBi; await cmd.ExecuteReaderExtAsync((reader) => { expiresOn = reader.AsNullable <DateTime>("ExpiresOn"); accessToken = reader.StringOrBlank("AccessToken").Trim(); resource = reader.ValueOrDefault <Models.AzureResources>("Resource", Models.AzureResources.AzureResource_PowerBi); clientId = reader.StringOrBlank("ClientId"); clientSecret = reader.StringOrBlank("ClientSecret"); user = reader.StringOrBlank("User"); password = Encryptor.Current.Decrypt(reader.BytesOrNull("Password")); tenantId = reader.StringOrDefault("TenantId", null); return(false); }); if (string.IsNullOrWhiteSpace(accessToken) || !expiresOn.HasValue || expiresOn.Value < DateTime.UtcNow) { TokenInfo token = await Token.GetGrantTypePasswordAsync( resource, clientId, clientSecret, user, password, tenantId ); using (SqlCommand cmdu = new SqlCommand() { CommandType = CommandType.Text, CommandText = "update AzureAccount set AccessToken=@accessToken, ExpiresOn=@expiresOn where AccountId=@accountId", Connection = cnn, Transaction = trn, }) { cmdu.Parameters.AddWithValue("@accountId", accountId); cmdu.Parameters.AddWithValue("@accessToken", token.AccessToken); cmdu.Parameters.AddWithValue("@expiresOn", token.ExpiresOn.AddMinutes(-1)); // allow 1 minute to avoid issues cmdu.ExecuteNonQuery(); } accessToken = token.AccessToken; } } }); return(accessToken); }
public static async Task <TokenInfo> GetGrantTypePasswordAsync( Models.AzureResources _resource, string _clientId, string _clientSecret, string _user, string _password, string _tenantId = null ) { TokenInfo token = null; List <KeyValuePair <string, string> > vals = new List <KeyValuePair <string, string> >(); vals.Add(new KeyValuePair <string, string>("scope", "openid")); switch (_resource) { case Models.AzureResources.AzureResource_PowerBi: vals.Add(new KeyValuePair <string, string>("resource", "https://analysis.windows.net/powerbi/api")); // TODO: move URL to config file break; default: throw new ApplicationException("Resource is required."); } if (string.IsNullOrWhiteSpace(_clientId)) { throw new ApplicationException("Client ID is required."); } vals.Add(new KeyValuePair <string, string>("client_id", _clientId.Trim())); if (!string.IsNullOrWhiteSpace(_clientSecret)) { vals.Add(new KeyValuePair <string, string>("client_secret", _clientSecret.Trim())); } vals.Add(new KeyValuePair <string, string>("grant_type", "password")); vals.Add(new KeyValuePair <string, string>("username", (_user ?? "").Trim())); vals.Add(new KeyValuePair <string, string>("password", (_password ?? "").Trim())); string url = string.Format("https://login.windows.net/{0}/oauth2/token", (_tenantId ?? "common").Trim()); // TODO: move URL to config file HttpClient client = new HttpClient(); HttpResponseMessage response = await client.PostAsync(url, new FormUrlEncodedContent(vals)); string responseData = ""; using (Stream data = await response.Content.ReadAsStreamAsync()) using (StreamReader reader = new StreamReader(data, System.Text.Encoding.UTF8)) { responseData = await reader.ReadToEndAsync(); } if (!string.IsNullOrWhiteSpace(responseData)) { JavaScriptSerializer jss = new JavaScriptSerializer(); jss.RegisterConverters(new[] { new TokenInfoConverter() }); if (response.IsSuccessStatusCode) { token = jss.Deserialize <TokenInfo>(responseData); } else { throw jss.Deserialize <AzureTokenException>(responseData); // cannot throw from inside converter (different call context) } } return(token); }