Generates the token but does not execute the azure url - c#

I need to get this service from c # https://learn.microsoft.com/en-us/rest/api/power-bi-embedded/capacities/resume.
For this I use the GetAccessToken () function to obtain the authentication token.
public string GetAccessToken()
{
try
{
string tenantId = "ae4e3a81-xxxxxxxxxxxxxxxxxx";
string clientId = "ca8393b2-xxxxxxxxxxxxxxxxxxxxxxxxx";
string clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
string authContextURL = "https://login.windows.net/" + tenantId;
var authenticationContext = new AuthenticationContext(authContextURL);
var credential = new ClientCredential(clientId: clientId, clientSecret: clientSecret);
var result = authenticationContext.AcquireTokenAsync(resource: "https://management.azure.com/", clientCredential: credential).Result;
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken.ToString();
return token;
}
catch (Exception ex)
{
return ex.ToString();
}
}
Then I use the DoWork () method to use the token and be able to consume the azure ulr.
public void DoWork()
{
string Subscription = "afdbf38c-c33c-45ea-8e9b-===========";
string token = GetAccessToken();
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
client.BaseAddress = new Uri("https://management.azure.com/");
// Now you can party with your HttpClient!
using (var response = client.PostAsync($"/subscriptions/{Subscription}/resourceGroups/Reportes/providers/Microsoft.PowerBIDedicated/capacities/powerbiembeddedjre1/resume?api-version=2017-10-01", null).Result)
{
response.EnsureSuccessStatusCode();
}
}
}
But when I go to check the response it generates an error message:
{StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content:
System.Net.Http.StreamContent, Headers: {Pragma: no-cache
x-ms-failure-cause: gateway x-ms-request-id:
02d9df62-0529-4a7f-b492-36ce8584aad6 x-ms-correlation-request-id:
02d9df62-0529-4a7f-b492-36ce8584aad6 x-ms-routing-request-id:
CANADACENTRAL: 20191114T163756Z: 02d9df62-052949-7 36ce8584aad6
Strict-Transport-Security: max-age = 31536000; includeSubDomains
X-Content-Type-Options: nosniff Connection: close Cache-Control:
no-cache Date: Thu, 14 Nov 2019 16:37:55 GMT Content-Length: 503
Content-Type: application / json; charset = utf-8 Expires: -1}}
What do I need to solve this problem?

looks like an issue with the bearer token, try client.SetBearerToken(token);
alternatively it's correctly sending back 403 because you do not meet the requirements for the claims (tenet/client issue).

Related

C# REST Api always return 401 status code when i am calling API by HttpClient

I am working with Nasdaq Fund Network Data Service first time. i am calling their one of the API where passing user id,pwd and access key but always getting 401 status code. i am not able to figure out what is wrong in my http call. please some one have a look at the code and tell me where i made the mistake for which i am getting 401 status code instead of right response.
here is my sample code where i could not share actual credentials and access key.
giving the code
string url = "sample url";
Uri u = new Uri(url);
string username = "test1";
string password = "test2";
string accessKey = "myaccesskey";
var payload = new Dictionary<string, string>
{
{"username", username},
{"password", password},
{ "accessKey", accessKey}
};
string strPayload = JsonConvert.SerializeObject(payload);
//HttpContent c = new StringContent(strPayload, Encoding.UTF8, "application/json");
HttpContent c = new StringContent(strPayload, Encoding.UTF8, "application/x-www-form-urlencoded");
var response = string.Empty;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
using (var client = new HttpClient())
{
HttpRequestMessage request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = u,
Content = c
};
var result = client.SendAsync(request).Result;
if (result.IsSuccessStatusCode)
{
response = result.StatusCode.ToString();
}
}
This Error i am getting
{StatusCode: 401, ReasonPhrase: 'Check Username/Password or Access
Key', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: {
Pragma: no-cache X-Frame-Options: SAMEORIGIN Cache-Control:
no-cache Date: Wed, 10 Aug 2022 11:55:36 GMT Content-Length: 0
Expires: -1 }}
Try the following in order to extract the JWT token you receive as a response.
var url = "https://nfn.nasdaq.com/servicecall/tempsession";
var formDataDictionary = new Dictionary<string, string>
{
{ "username", "test1"},
{ "password", "test2"},
{ "accessKey", "myaccesskey"}
};
var formData = new FormUrlEncodedContent(formDataDictionary);
using (var client = new HttpClient())
{
var response = await client.PostAsync(url, formData);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
var responseBody = JObject.Parse(result);
var accessToken = responseBody["data']"].Value<string>();
}

ASP.NET Core HttpClient request returns 200 when webapi returns 406

I'm trying to do simple login with httpclient post request but the client side only returns 200 instead of anything else with bad credentials. Below are my code
Consumer Side
[HttpPost("/login")]
public async Task<IActionResult> Login(LoginUser loginUser)
{
string redirectPage = "LoginPage";
// string result = "";
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:5000/webapi");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.PostAsJsonAsync("login", loginUser);
Console.WriteLine(response);
if (response.ReasonPhrase == "OK")
{
redirectPage = "Success";
}
else
{
Console.WriteLine("Bad Login");
redirectPage = "LoginPage";
}
}
}
API Side
[HttpPost]
public string Login(object data)
{
HttpResponseMessage loginResponse;
UserLogin credentials = JsonConvert.DeserializeObject<UserLogin>(data.ToString());
Console.WriteLine(credentials.Username + " " + credentials.Password);
User dbUser = db.Users.FirstOrDefault(user => user.Username == credentials.Username);
User dbUserPw = db.Users.FirstOrDefault(user => user.Password == credentials.Password);
if (dbUser != null && dbUserPw != null){
loginResponse = new HttpResponseMessage(HttpStatusCode.OK);
}
else{
loginResponse = new HttpResponseMessage(HttpStatusCode.NotAcceptable);
}
Console.WriteLine(loginResponse);
return loginResponse.StatusCode.ToString();
}
and when I try to log in with incorrect credentials
the API side returns
StatusCode: 406, ReasonPhrase: 'Not Acceptable', Version: 1.1, Content: <null>, Headers:
{
}
but the client side returns
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Date: Tue, 08 Jun 2021 23:12:48 GMT
Server: Kestrel
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
}
would anyone know what the problem would be?
According to your description, I found your response type is string and you just return a string response to the client side.
This is the reason why you always get 200 status codes.
If you want to return the 406 status codes, I suggest you could use ContentResult instead of IActionResult.
[HttpPost]
public IActionResult Login(object data)
{
return new ContentResult() { Content = "aaa", StatusCode = (int?)HttpStatusCode.NotAcceptable };
}
Result:
I resolved this by changing PostJsonAsync method to
var response = client.PostAsJsonAsync("login", loginUser).Result.Content.ReadAsStringAsync();

Unauthorized error when posting data in Azure Eventhub

I am doing a POC on sending data to Azure event hub using C#. The data will be posted over http unlike the Eventhub client. As per the requirements I cam creating a SAStoken to be embedded in http header. However when posting I get 501, Unauthorized access error. Not sure where I am going wrong. Here is the code that I have written
public static async Task<HttpResponseMessage> SendDataUsingHttp()
{
// Namespace info.
var serviceNamespace = "myeventhubs";
var hubName = "eventhub1";
var url = string.Format("{0}/publishers/{1}/messages", hubName, 1);
//var url = string.Format("{0}/messages", hubName);
var baseUri = new
Uri(string.Format("https://{0}.servicebus.windows.net/"
, serviceNamespace));
var SharedAccessKeyName = "All";
var SharedAccessKey = "<shared access key>";
var sasToken =
createSasToken(baseUri.ToString(),SharedAccessKeyName,
SharedAccessKey);
var evtData = new
{
Temperature = new Random().Next(20, 50)
};
var payload = JsonConvert.SerializeObject(evtData);
// Create client.
var httpClient = new HttpClient
{
BaseAddress = baseUri
};
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Authorization = new
System.Net.Http.Headers.AuthenticationHeaderValue
("SharedAccessSignature", sasToken);
var content = new StringContent(payload, Encoding.UTF8);
content.Headers.ContentType = new
System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
HttpResponseMessage result = null;
try
{
result = await httpClient.PostAsync(url, content);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return result;
}
private static string createSasToken(string baseUri, string keyName,
string key)
{
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var week = 60 * 60 * 24 * 7;
var expiration = Convert.ToString((int)sinceEpoch.TotalSeconds +
week);
string stringToSign = HttpUtility.UrlEncode(baseUri) + "\n" +
expiration;
HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key)); //--
var signature =
Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(
stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture,
"SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(baseUri), HttpUtility.UrlEncode(signature),
expiration, keyName);
return sasToken;
}
result
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1,
Content: System.Net.Http.StreamContent, Headers: {
Transfer-Encoding: chunked Strict- Transport-Security:
max-age=31536000 Date: Sun, 17 Jun 2018 08:35:43 GMT Server:
Microsoft-HTTPAPI/2.0 Content-Type: application/xml; charset=utf-8
}} Content: {System.Net.Http.StreamContent} Headers:
{Transfer-Encoding: chunked Strict-Transport-Security:
max-age=31536000 Date: Sun, 17 Jun 2018 08:35:43 GMT Server:
Microsoft-HTTPAPI/2.0
Based on your createSasToken method, it would generate the authorization header value with the following format:
Authorization: SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}
For your request, you also specify the following code:
System.Net.Http.Headers.AuthenticationHeaderValue("SharedAccessSignature", sasToken);
Using Fiddler to capture the network traces, you would find that your authorization header value in your sent request would look like this:
Authorization: SharedAccessSignature SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}
For your code, you need to adjust the format of your sasToken under the createSasToken method.
Moreover, the baseUri parameter of createSasToken method needs to be the full request path you are requesting. So you need to modify the related code under SendDataUsingHttp for generating the token as follows:
var sasToken =createSasToken(baseUri+url, SharedAccessKeyName, SharedAccessKey);

Forbidden access when calling twitter api geo/search.json

I'm new in using twitter API, I've successfully called:
https://api.twitter.com/1.1/statuses/user_timeline.json
api.twitter.com/1.1/followers/list.json
but when I call:
https://api.twitter.com/1.1/geo/search.json?query=Pakistan
I get Forbidden access.
Following is my request:
Method: GET, RequestUri: 'https://api.twitter.com/1.1/geo/search.json?query=Pakistan', Version: 1.1, Content: , Headers:
{
Authorization: Bearer xxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyzzzzzzzzzzzzzzzzzzzzzzzzz%aaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbb
}
And the response that I get is:
StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
strict-transport-security: max-age=631138519
x-connection-hash: 3a7f405036803861a700cef30f7b1e7f
x-response-time: 107
Date: Fri, 05 May 2017 03:18:15 GMT
Set-Cookie: guest_id=v1%3A149395429589966721; Domain=.twitter.com; Path=/; Expires=Sun, 05-May-2019 03:18:15 UTC
Server: tsa_o
Content-Length: 91
Content-Type: application/json; charset=utf-8
}
If you're interested in looking at my C# code that I'm using, here you go:
public async Task<IEnumerable<string>> GetTweetsByLatLong(double latitude, double longitude, int count, string accessToken = null)
{
if (accessToken == null)
{
accessToken = await GetAccessToken();
}
var requestUserTimeline = new HttpRequestMessage(HttpMethod.Get, string.Format("https://api.twitter.com/1.1/geo/search.json?query=Pakistan"));
requestUserTimeline.Headers.Add("Authorization", "Bearer " + accessToken);
var httpClient = new HttpClient();
HttpResponseMessage responseUserTimeLine = await httpClient.SendAsync(requestUserTimeline);
if (responseUserTimeLine.IsSuccessStatusCode)
{
var serializer = new JavaScriptSerializer();
dynamic json = ((serializer.Deserialize<object>(await responseUserTimeLine.Content.ReadAsStringAsync())) as Dictionary<string, object>).Values.ElementAt(0);
//new System.Collections.Generic.Mscorlib_DictionaryValueCollectionDebugView<string, object>((json as Dictionary<string, object>).Values).Items[0]
var enumerableTwitts = (json as IEnumerable<dynamic>);
if (enumerableTwitts == null)
{
return null;
}
return enumerableTwitts.Select(t => (string)(t["name"].ToString()));
}
else
{
return new string[] { responseUserTimeLine.ToString() };
}
}
public async Task<string> GetAccessToken()
{
var httpClient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://api.twitter.com/oauth2/token ");
var customerInfo = Convert.ToBase64String(new UTF8Encoding().GetBytes(OAuthConsumerKey + ":" + OAuthConsumerSecret));
request.Headers.Add("Authorization", "Basic " + customerInfo);
request.Content = new StringContent("grant_type=client_credentials", Encoding.UTF8, "application/x-www-form-urlencoded");
HttpResponseMessage response = await httpClient.SendAsync(request);
string json = await response.Content.ReadAsStringAsync();
var serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>(json);
return item["access_token"];
}
I believe it is because you are using Application-only authentication by providing a Bearer token.
See "Requires Authentication" in both
https://dev.twitter.com/rest/reference/get/geo/search
and
https://dev.twitter.com/rest/reference/get/statuses/user_timeline
And read https://dev.twitter.com/oauth

Updating Dynamics CRM entries in C#

I am trying to find out how to update data in Dynamics CRM and I fail miserably.
private const string Url = "*****/XRMServices/2011/OrganizationData.svc/";
private const string userName = "username";
private const string password = "password";
private readonly HttpClientHandler _handler;
NetworkCredential credentials = new NetworkCredential(userName, password);
_handler = new HttpClientHandler { Credentials = credentials };
public void Put()
{
StringContent content = new StringContent("<feed><entry><content><m:properties><d:Address1_Country>NEW VALUE</d:Address1_Country></m:properties></content></entry></feed>");
using (HttpClient client = new HttpClient(_handler))
{
client.PutAsync(Url + "AccountSet(guid'182df667-c4f6-e111-8042-0050568e0828')", content).Result;
}
}
The response I get is:
response = {StatusCode: 415, ReasonPhrase: 'Unsupported Media Type', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
DataServiceVersion: 1.0;
Persistent-Auth: true
Cache-Control: private
Date: Tue, 10 Mar 2015 10:22:07 GMT
Server: Micr...
You are trying to use OData endpoint that would not work outside of CRM webresources. Try to use SOAP endpoint for your purpose:
https://msdn.microsoft.com/en-us/library/gg334754.aspx
https://msdn.microsoft.com/en-us/library/gg328416.aspx

Categories