Issue on creating token on oauth2 - c#

I have this code in C#, however, I'm having an issue on the line
var response = await client.PostAsync(url, new FormUrlEncodedContent(data));
I get this error
StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content:
When I try it in Postman, it successfully creates the token, but not in C#.
string url = "https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token";
var data = new Dictionary<string, string>
{
{ "grant_type", "client_credentials" },
{ "scope", "https://outlook.office365.com/.default" },
{ "client_id", client_id },
{ "client_secret", client_secret }
};
HttpClient client = new HttpClient();
var response = await client.PostAsync(url, new FormUrlEncodedContent(data));
return await response.Content.ReadAsAsync<AccessTokenModel>();

Updating .Netframework from 4.5 to 4.6 resolve the 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>();
}

Creating an issue using JIRA Rest API returns HTTP status code 200 but the issue is not created

I want to create an issue with Jira Rest API using C#
string data = #"{ ""fields"": {
""project"":
{
""key"": ""TOTEM""
},
""summary"": ""just a test"",
""description"": ""Creating of an issue using project keys and issue type names using the REST API"",
""issuetype"": {
""name"": ""Task""
},
""assignee"": { ""name"": ""imane.elbarchi"" }
}
}";
//Console.WriteLine(data);
string uri = "https://proactioneu.ent.cgi.com/rest/api/latest/issue";
System.Net.Http.HttpClient client = new HttpClient();
//Putting URI in client base address.
client.BaseAddress = new Uri(uri);
//Putting the credentials as bytes.
byte[] cred = UTF8Encoding.UTF8.GetBytes("username:password");
//Putting credentials in Authorization headers.
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred));
//Putting content-type into the Header.
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
//I am using StringContent because I am creating console application, no any serialize I used for manipulate the string.
var content = new StringContent(data, Encoding.UTF8, "application/json");
System.Net.Http.HttpResponseMessage response = client.PostAsync("issue", content).Result;
Console.WriteLine(response);
Console.ReadKey();
}
}
}
and I get a response like:
StatusCode: 200, ReasonPhrase: 'Found', Version: 1.0, Content:
System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
Cache-Control: no-cache
Connection: close
Content-Type: text/html
}
but the issue is not created.
I think it is because of this line:
System.Net.Http.HttpResponseMessage response = client.PostAsync("issue", content).Result;
When I create an issue I use:
var response = await httpClient.PostAsync(httpClient.BaseAddress, content);
So the first parameter wants the url you want to send the content to. "issue" is not an url.
My code looks like this. Maybe you can use it.
public async Task<bool> PostIssueAsync(string userpass, string data)
{
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(Constants.JiraUrl + "rest/api/latest/issue");
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", userpass);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(data, Encoding.UTF8, "application/json");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
try
{
var response = await httpClient.PostAsync(httpClient.BaseAddress, content);
return response.IsSuccessStatusCode;
}
catch (Exception ex)
{
Console.WriteLine(ex);
return false;
}
}

Issue Exchanging Authorization Code for Token Google Api

I have checked every thing repeatedly and does not seem to have any issue in code or logic.
Here is the code:
var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{"grant_type", "authorization_code"},
{"code", code},
{"redirect_uri", redirectUri.ToString()},
{"client_id", clientId},
{"client_secret", clientSecret}
});
string token = string.Empty;
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var response = client.PostAsync(tokenEndpoint, content);
var responseContent = response.Result.Content.ReadAsStringAsync();
token = responseContent.ToString();
if (!response.Result.IsSuccessStatusCode) ;
}
return token;
And i am getting error:
"error": "redirect_uri_mismatch",
"error_description": "Bad Request"
The Url of the above page is : http://localhost:62188/dashboard/googleSync.aspx
And in Google Console i have this Url as Authorized Return Url :
So what am i missing here?
Ok: had to use this : :redirect_uri = "postmessage" and it worked.

Create a new user in Azure Active Directory (B2C) with Graph API, using http post request

I have previously been adding users programmatically using Active Directory Authentication Library (ADAL), but now I need to define "signInNames" (= users email), and that doesn't seem to be possible with ADAL (please tell me if im wrong).
Now I'm trying to add a new user (local account) programmatically using HTTP POST, following the documentation on MSDN.
//Get access token (using ADAL)
var authenticationContext = new AuthenticationContext(AuthString, false);
var clientCred = new ClientCredential(ClientId, ClientSecret);
var authenticationResult = authenticationContext.AcquireTokenAsync(ResourceUrl, clientCred);
var token = authenticationResult.Result.AccessToken;
//HTTP POST CODE
const string mail = "new#email.com";
// Create a new user object.
var user = new CustomUser
{
accountEnabled = true,
country = "MS",
creationType = "LocalAccount",
displayName = mail,
passwordPolicies = "DisablePasswordExpiration,DisableStrongPassword",
passwordProfile = new passwordProfile { password = "jVPmEm)6Bh", forceChangePasswordNextLogin = true },
signInNames = new signInNames { type = "emailAddress", value = mail }
};
var url = "https://graph.windows.net/" + TenantId + "/users?api-version=1.6";
var jsonObject = JsonConvert.SerializeObject(user);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = client.PostAsync(url,
new StringContent(JsonConvert.SerializeObject(user).ToString(),
Encoding.UTF8, "application/json"))
.Result;
if (response.IsSuccessStatusCode)
{
dynamic content = JsonConvert.DeserializeObject(
response.Content.ReadAsStringAsync()
.Result);
// Access variables from the returned JSON object
var appHref = content.links.applications.href;
}
}
But i have no success, getting this response:
{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content:....}
Any ideas what i should do? I succeeded using Powershell-script, but I need to do this in my C# app.
Thank you for your response Fei Xue, i believe i had the right permissions. What i did to solvem my problem.
First off i removed my own custom class "NewUser", then i downloaded this sample-project: https://github.com/AzureADQuickStarts/B2C-GraphAPI-DotNet/blob/master/B2CGraphClient/B2CGraphClient.cs to eliminate the risk that my code was wrong. I modified it to support my needs, then i created a simple JObject:
var jsonObject = new JObject
{
{"accountEnabled", true},
{"country", customer.CustomerBase.Company},
{"creationType", "LocalAccount"},
{"displayName", pendingCustomer.Email.Trim()},
{"passwordPolicies", "DisablePasswordExpiration,DisableStrongPassword"},
{"passwordProfile", new JObject
{
{"password", pwd},
{"forceChangePasswordNextLogin", true}
} },
{"signInNames", new JArray
{
new JObject
{
{"value", pendingCustomer.Email.Trim()},
{"type", "emailAddress"}
}
}
}
};
client = new B2CGraphClient(ClientId, ClientSecret, TenantId);
var response = await client.CreateUser(jsonObject.ToString());
var newUser = JsonConvert.DeserializeObject<User>(response);
From B2CGraphClient.cs
private async Task<string> SendGraphPostRequest(string api, string json)
{
// NOTE: This client uses ADAL v2, not ADAL v4
var result = authContext.AcquireToken(Globals.aadGraphResourceId, credential);
var http = new HttpClient();
var url = Globals.aadGraphEndpoint + tenant + api + "?" + Globals.aadGraphVersion;
var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await http.SendAsync(request);
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
var formatted = JsonConvert.DeserializeObject(error);
//Console.WriteLine("Error Calling the Graph API: \n" + JsonConvert.SerializeObject(formatted, Formatting.Indented));
Logger.Error("Error Calling the Graph API: \n" + JsonConvert.SerializeObject(formatted, Formatting.Indented));
}
Logger.Info((int)response.StatusCode + ": " + response.ReasonPhrase);
return await response.Content.ReadAsStringAsync();
}
This finally solved all my problems, it was probably an format-error in the serialization of my NewCustomer-class, which then got rejected by the API.
Did you grant the app sufficient permission to operate users? The create user REST API works well for me for the B2C tenant.
Here are the steps I tested:
1.Create the app via the PowerShell below
PowerShell:
$bytes = New-Object Byte[] 32
$rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$rand.GetBytes($bytes)
$rand.Dispose()
$newClientSecret = [System.Convert]::ToBase64String($bytes)
New-MsolServicePrincipal -DisplayName "My New B2C Graph API App" -Type password -Value
2.Grant the app to User Account Administrator role.
Add-MsolRoleMember -RoleObjectId fe930be7-5e62-47db-91af-98c3a49a38b1 -RoleMemberObjectId 7311370c-dac3-4f34-b2ce-b22c2a5a811e -RoleMemberType servicePrincipal
3.Get the token for the app with client credential flow
POST: https://login.microsoftonline.com/adb2cfei.onmicrosoft.com/oauth2/token
grant_type=client_credentials&client_id={AppPrincipalId return by PowerShell}&client_secret={client_secret}&resource=https%3A%2F%2Fgraph.windows.net
4.Create the user with REST below:
POST: https://graph.windows.net/adb2cfei.onmicrosoft.com/users?api-version=1.6
authorization: bearer {token}
content-type: application/json
{
"accountEnabled": true,
"creationType": "LocalAccount",
"displayName": "Alex Wu",
"passwordProfile": {
"password": "Test1234",
"forceChangePasswordNextLogin": false
},
"signInNames": [
{
"type": "userName",
"value": "AlexW"
},
{
"type": "emailAddress",
"value": "AlexW#example.com"
}
]
}

HttpClient post request for WebApi using asp.net mvc application

I'm trying to consume WebApi but I'm having issues. My 'IsSuccessStatusCode' is always false and I have 404 in response.
I have tried multiple methods but can't be able to do it correctly.
Constants:
const string baseUri = ""; // base url of API
const string setDealFlagUri = "Deals/SetDealFlag";
Method 1, using PostAsync:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUri);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("deadId", "3"),
new KeyValuePair<string, string>("flagValueToSet", "true")
});
var response = await client.PostAsync(setDealFlagUri, content);
if (response.IsSuccessStatusCode)
{
return true;
}
}
Method 2, using PostAsJsonAsync:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUri);
DealFlag content = new DealFlag
{
deadId = 3,
flagValueToSet = true
};
var response = await client.PostAsJsonAsync(setDealFlagUri, content);
if (response.IsSuccessStatusCode)
{
return true;
}
}
WebApi request detail:
Curl:
curl -X POST --header 'Accept: application/json' '{baseApiurl}/Deals/SetDealFlag?dealId=3&flagValueToSet=true'
Request URL
{baseApiurl}/Deals/SetDealFlag?dealId=3&flagValueToSet=true
Response Body
{
"Successful": true,
"ErrorMessages": [],
"ValidationResults": {
"IsValid": false,
"ValidationErrors": []
}
}
Response Headers
{
"pragma": "no-cache",
"date": "Wed, 24 Aug 2016 18:38:01 GMT",
"content-encoding": "gzip",
"server": "Microsoft-IIS/8.0",
"x-aspnet-version": "4.0.30319",
"x-powered-by": "ASP.NET",
"vary": "Accept-Encoding",
"content-type": "application/json; charset=utf-8",
"cache-control": "no-cache",
"content-length": "198",
"expires": "-1"
}
Please help me to use this webapi function correctly.
Thanks!
I think that the problem is that your controller method has signature like
[HttpPost]
public HttpResponseMessage SetDealFlag(int dealId, bool flagValueToSet)
Am I right? If your answer is "Yes" so your method wants parameters in the URL.
And so you get 404 error becouse no one of yours Web API methods matches to that URL.
Send your parameters dealId and flagValueToSet in the URL is the solution.
I wrote simple console app for testing my theory and it works perfectly:
public static void Main(string[] args)
{
using (var client = new HttpClient())
{
try
{
// Next two lines are not required. You can comment or delete that lines without any regrets
const string baseUri = "{base-url}";
client.BaseAddress = new Uri(baseUri);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("deadId", "3"),
new KeyValuePair<string, string>("flagValueToSet", "true")
});
// response.Result.IsSuccessStatusCode == true and no errors
var response = client.PostAsync($"{baseUri}/Deals/SetDealFlag?dealId=3&flagValueToSet=true", null);
// response.Result.IsSuccessStatusCode == false and 404 error
// var response = client.PostAsync($"{baseUri}/Deals/SetDealFlag", content);
response.Wait();
if (response.Result.IsSuccessStatusCode)
{
return;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
}

Categories