Google Authentication with WebApi - BadRequest - c#

Code in Node.Js
var url = 'https://accounts.google.com/o/oauth2/token';
var params = {
client_id: req.body.clientId,
redirect_uri: req.body.redirectUri,
code: req.body.code,
grant_type: 'authorization_code',
client_secret: config.GOOGLE_SECRET
};
console.log(req.body.code);
request.post(url, {
json: true,
form: params
}, function (err, response, token) {
var accessToken = token.access_token;
)};
Code in Web Api
var clientd = new ClientD()
{
client_id = client_id,
redirect_uri = redirect_uri,
client_secret = client_secret,
code = code,
grant_type = grant_type
};
String url = "https://accounts.google.com/o/oauth2/token";
using (var client = new System.Net.Http.HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add
(new MediaTypeWithQualityHeaderValue("application/json"));
var json = Newtonsoft.Json.JsonConvert.SerializeObject(clientd);
HttpContent content = new StringContent(json);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var httpResponseMessage = await client.PostAsync(url, content);
if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
{
return httpResponseMessage.StatusCode.ToString();
}
else
{
return httpResponseMessage.StatusCode.ToString();
}
}
I have a code for google authentication in node.js which is working fine. When I try to re-write the code in a controller of wep-api I get a bad request error.
Where am I going wrong ? Any help ?
Note: The client-id's and other info are perfectly set in both the cases.

Related

How to get access token, refresh token in .NET Core (C#) without using SDK (Manually) in QuickBooks Online API?

I have created a simple console app in C#, I need to request access token without using SDK. I have managed to launch a URL to request code. I get code but trying to call the access_token endpoint is a challenge. I need help on how I can get access_token and refresh_token. Attached is the screenshot of codes having all the request details and the endpoint I used as follows.
Endpoint used: https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer
Parameters: code,=[codeReceived] grant_type = authorization_code and redirect_uri = [RedirectUrl]
Headers:Authorization: Basic [Base64EncodedBytes], Accept: application/json, Host: oauth.platform.intuit.com, Content-Type: application/x-www-form-urlencoded
I have created a simple console app in C#, I need to request access token without using SDK. I have managed to launch a URL to request code. I get code but trying to call the access_token endpoint is a challenge. I need help on how I can get access_token and refresh_token. Attached is the screenshot of codes having all the request details and the endpoint I used as follows.
Posting
Endpoint used: https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer
Parameters:[enter image description here][1]
code,=[codeReceived] grant_type = authorization_code and redirect_uri = [RedirectUrl]
Headers:
Authorization: Basic [Base64EncodedBytes], Accept: application/json, Host: oauth.platform.intuit.com, Content-Type: application/x-www-form-urlencoded
This is the Client Class I've created:
public class RestClient
{
public string ClientID;
public string ClientSecret;
public string RedirectUrl = "https://devices.pythonanywhere.com/";
public string Environment = "sandbox";
private async Task<string> GetAccessTokenAsync(string Url, string code, string ClientId, string ClientSecret)
{
var stringBytes = Encoding.UTF8.GetBytes($"{ClientId}:{ClientSecret}");
var encodedBytes = Convert.ToBase64String(stringBytes);
var uriBuilder = new UriBuilder(Url);
var query = HttpUtility.ParseQueryString(uriBuilder.Query);
query["grant_type"] = "authorization_code";
query["code"] = $"{code}";
query["redirect_uri"] = $"{RedirectUrl}";
uriBuilder.Query = query.ToString();
Url = uriBuilder.ToString();
var DecodedUrl = HttpUtility.UrlDecode(Url);
Console.WriteLine(encodedBytes);
HttpRequestMessage request = new(HttpMethod.Post, DecodedUrl);
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", $"Basic {encodedBytes}");
request.Headers.Add("Host", "oauth.platform.intuit.com");
request.Content = new StringContent("application/x-www-form-urlencoded");
using HttpClient client = new();
using HttpResponseMessage response = await client.SendAsync(request);
var body = response.Content.ReadAsStringAsync();
return body.Result;
}
public string GetTokens(string Url, string code, string ClientId, string ClientSecret)
{
try
{
var response = GetAccessTokenAsync(Url, code, ClientId, ClientSecret).Result;
if (response.Length>0)
{
return "There is data";
}
return "No data";
}
catch (Exception ex)
{
return ex.Message;
}
}
}
and this here is where I'm calling it
class Program
{
static void Main(string[] args)
{
var client = new RestClient();
client.ClientID = "AB8EMz5arbI**************************************";
client.ClientSecret = "4y4vsz*********************************";
var OauthUrl = "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer";
var code = "AB11644908535RgJ**************************";
Console.WriteLine($"Response: {client.GetTokens(OauthUrl, code, client.ClientID, client.ClientSecret)}");
}
}
I was making a mistake in my C# code. Here is the working code that I used in GetAccessTokenAsync:
private async Task<string> GetAccessTokenAsync(string Url, string code, string ClientId, string ClientSecret)
{
var stringBytes = Encoding.UTF8.GetBytes($"{ClientId}:{ClientSecret}");
var encodedBytes = Convert.ToBase64String(stringBytes);
HttpRequestMessage request = new(HttpMethod.Post, Url);
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Authorization", $"Basic {encodedBytes}");
var contentList = new List<string>();
contentList.Add("grant_type=authorization_code");
contentList.Add($"code={code}");
contentList.Add($"redirect_uri={RedirectUrl}");
request.Content = new StringContent(string.Join("&", contentList));
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
using HttpClient client = new();
using HttpResponseMessage response = await client.SendAsync(request);
var body = response.Content.ReadAsStringAsync();
return body.Result;
}
I hate reviving old threads, but your answer helped me a lot. I had to change it a little bit to accept the refresh token rather than authorization code and thought I would post it here. I banged my head around for quite some time trying to figure this out without any useful documentation that I could find on the matter. I hope it helps someone in the same way that your code has helped me. Thanks!
public async Task<string> RefreshAccessToken(string Url, string RefreshToken, string ClientId, string ClientSecret)
{
var stringBytes = Encoding.UTF8.GetBytes($"{ClientID}:{ClientSecret}");
var encodedBytes = Convert.ToBase64String(stringBytes);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, Url);
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("Authorization", $"Basic {encodedBytes}");
var contentList = new List<string>();
contentList.Add("grant_type=refresh_token");
contentList.Add($"refresh_token={RefreshToken}");
request.Content = new StringContent(string.Join("&", contentList));
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.SendAsync(request))
{
var body = response.Content.ReadAsStringAsync();
return body.Result;
}
}
}
Alternatively, I find that something like this works too. Using RestSharp..
public string RefreshAccessToken()
{
try
{
var stringBytes = Encoding.UTF8.GetBytes($"{strClientID}:{strClientSecret}");
var encodedBytes = Convert.ToBase64String(stringBytes);
var client = new RestClient("https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer");
client.UseJson();
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", $"Basic {encodedBytes}");
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("grant_type", "refresh_token");
request.AddParameter("refresh_token", CurrentRefreshToken);
IRestResponse response = client.Execute(request);
return response.Content;
}
catch (Exception ex)
{
WriteError("RefreshAccessToken() - " + ex.Message);
return ex.Message;
}
}

I am trying to update an item in a sharepoint list but its returning Bad Request .NET core

class Program
{
public static async Task<bool> Post(string siteUrl, string requestUri, HttpContent content)
{
var credential = new System.Net.NetworkCredential(
"User",
"Pass",
"Domain");
using (var handler = new HttpClientHandler() { Credentials = credential, UseProxy = false })
{
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Accept.Clear();
var mediaType = new MediaTypeWithQualityHeaderValue("application/json");
mediaType.Parameters.Add(new NameValueHeaderValue("odata", "nometadata"));
client.DefaultRequestHeaders.Accept.Add(mediaType);
client.DefaultRequestHeaders.Add("X-RequestDigest", await GetRequestDigest());
string url = string.Format(requestUri, siteUrl);
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
return true;
}
}
}
static async Task Main(string[] args)
{
string domain = "xxxx";
string SiteUrl = "https://SITE/";
string issuesListById = "{0}_api/web/lists/GetByTitle('issues')/items?$filter=ID eq 1";
string taskListUrlById = "{0}_api/web/lists/GetByTitle('tasks')/items?$filter=ID eq 932";
var credentials = new NetworkCredential("User", "Pass", domain);
var handler = new HttpClientHandler { Credentials = credentials };
using (var http = new HttpClient(handler))
{
var stringContent = new StringContent("", Encoding.UTF8, "application/json");
http.DefaultRequestHeaders.Accept.Clear();
http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await http.GetAsync(string.Format(taskListUrlById, SiteUrl)).ConfigureAwait(false);
string jsonData = await response.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<Tasks>(jsonData);
var itemToEdit = obj.Value.First();
itemToEdit.Status = "Close";
var content = new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json");
var update = await Post(SiteUrl, taskListUrlById, content);
}
}
}
I am trying to update the status of a task in a SharePoint list to "Close", I am using the post method to send the content, I am receiving "bad request" in the post method... I am using REST to communicate with SharePoint on Premise any idea on what causing this problem? (the GetRequestDigest function is working well). if someone can help... Thanks in Advance.
string taskListUrlById = "{0}_api/web/lists/GetByTitle('tasks')/items(932)"; //932 is the ID of the item to update
string SiteUrl = "yoursite";
string url = string.Format(taskListUrlById, SiteUrl);
string content = "{ '__metadata': { 'type': 'SP.Data.TasksListItem' }, 'Status': 'Close'}";
var credential = new System.Net.NetworkCredential("username",
"Password",
"domain");
using (var handler = new HttpClientHandler() { Credentials = credential, UseProxy = false })
{
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var request = new HttpRequestMessage(HttpMethod.Post, url);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Add("X-RequestDigest", await GetRequestDigest());
request.Headers.Add("X-HTTP-Method", "MERGE");
request.Headers.Add("IF-MATCH", "*");
HttpContent strContent = new StringContent(content);
strContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
strContent.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("odata", "verbose"));
request.Content = strContent;
var response = await client.SendAsync(request);
}
}

HttpClient form submission with json return

Thanks in advance.
We are working on an oAuth2 process and need some help. The requirement given is to POST to the server with form variables embedded, and expect a server response in JSON. The documentation has a similar sequence involving a GET request returning JSON and a very similar method grabs the response just fine. However, in this case it gives an object ref error saying the response is null. We are getting a 200 OK message from server with a content length of 1929, and it says content-type is application/json so I have every reason to believe the content is there somewhere.
public rsAccessToken Signup(string Code, string State, string redirect_uri)
{
HttpClient client = new HttpClient();
rsAccessToken rt = null;
HttpResponseMessage response = null;
client.BaseAddress = new Uri(URLtoken);
string grant_type = "authorization_code";
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var byteArray = Encoding.ASCII.GetBytes(string.Format("{0}:{1}", clientid, secret));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URLtoken);
var parameters = new Dictionary<string, string> { { "grant_type", grant_type }, { "code", Code }, { "state", State }, { "redirect_uri", redirect_uri } };
var encodedContent = new FormUrlEncodedContent(parameters);
Task task = client.PostAsync(URLtoken, encodedContent)
.ContinueWith((taskwithresponse) =>
{
Task<string> jsonString = response.Content.ReadAsStringAsync();
jsonString.Wait();
rt = JsonConvert.DeserializeObject<rsAccessToken>(jsonString.Result);
});
task.Wait();
client.Dispose();
return rt;
}
the response captured at the taskwithresponse point is:
Id = 104, Status = RanToCompletion, Method = "{null}", Result = "StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:\r\n{\r\n Connection: keep-alive\r\n Date: Mon, 14 Sep 2020 14:41:55 GMT\r\n ETag: W/\"789-W2Me6TSLLmO4+fEmAtfH4YWXhxs\"\r\n Set-Cookie: TS0108eb76=0119a2687f0aa2133862c3de61eb2485030f83265a0e1bcb62403e1c777052fccfeacf2df6a14e78b161afc6a43cfc2622532765bc; Max-Age=900; Path=/\r\n Content-Length: 1929\r\n Content-Type: application/json; charset=utf-8\r\n}"
Appreciate the help.
The correct code is:
public rsAccessToken VeteranSignup(string Code, string State, string redirect_uri)
{
HttpClient client = new HttpClient();
rsAccessToken rt = null;
client.BaseAddress = new Uri(URLtoken);
string grant_type = "authorization_code";
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var byteArray = Encoding.ASCII.GetBytes(string.Format("{0}:{1}", clientid, secret));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URLtoken);
var parameters = new Dictionary<string, string> { { "grant_type", grant_type }, { "code", Code }, { "state", State }, { "redirect_uri", redirect_uri } };
var encodedContent = new FormUrlEncodedContent(parameters);
Task task = client.PostAsync(URLtoken, encodedContent)
.ContinueWith((taskwithresponse) =>
{
Task<string> jsonString = taskwithresponse.Result.Content.ReadAsStringAsync();
jsonString.Wait();
rt = JsonConvert.DeserializeObject<rsAccessToken>(jsonString.Result);
});
task.Wait();
client.Dispose();
return rt;
}
You should use taskwithreponse
Also, you should use the pure aysnc chain. Don't make the aynsc call to sync call.
public async Task<rsAccessToken> Signup(string Code, string State, string redirect_uri)
{
using(HttpClient client = new HttpClient())
{
rsAccessToken rt = null;
client.BaseAddress = new Uri(URLtoken);
string grant_type = "authorization_code";
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var byteArray = Encoding.ASCII.GetBytes(string.Format("{0}:{1}", clientid, secret));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
var(HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, URLtoken))
{
var parameters = new Dictionary<string, string> { { "grant_type", grant_type }, { "code", Code }, { "state", State }, { "redirect_uri", redirect_uri } };
var encodedContent = new FormUrlEncodedContent(parameters);
HttpResponseMessage response = await client.PostAsync(URLtoken, encodedContent)
var jsonString = await response.Content.ReadAsStringAsync();
rt = JsonConvert.DeserializeObject<rsAccessToken>(jsonString.Result);
}
return rt;
}
}

Using HttpClient to GET

So, because HttpClient is "better," I need to convert WebClient to HttpClient, but it just doesn't work as expected. The following function uses WebClient and works like a charm.
private static void Authenticate()
{
Console.WriteLine("Authenticating . . .");
var clientId = ConfigurationManager.AppSettings["AuthNClientId"];
var uri = ConfigurationManager.AppSettings["AuthNUri"];
var userName = ConfigurationManager.AppSettings["AuthNUserName"];
var password = ConfigurationManager.AppSettings["AuthNPassword"];
var client = new WebClient();
string formData = $"client_id={clientId}&grant_type=password&username={userName}&password={password}";
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
var response = client.UploadString($"{uri}", formData);
dynamic authResult = JsonConvert.DeserializeObject(response);
_accessToken = authResult.access_token;
if (_accessToken == null)
{
throw new ApplicationException("Unable to authenticate. Check your configuration file <appSettings>.");
}
Console.WriteLine("Authenticated.");
}
This code, on the other hand, returns a BadRequest response code.
static async Task<string> GetAuthenticationToken()
{
string token = string.Empty;
var clientId = ConfigurationManager.AppSettings["AuthNClientId"];
var uri = ConfigurationManager.AppSettings["AuthNUri"];
var userName = ConfigurationManager.AppSettings["AuthNUserName"];
var password = ConfigurationManager.AppSettings["AuthNPassword"];
client.BaseAddress = new Uri("https://myurl.com/oauth2/token");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("ContentType", "application/x-www-form-urlencoded");
var path = $"client_id={clientId}&grant_type=password&username={userName}&password={password}";
HttpResponseMessage response = await client.GetAsync($"https://myurl.com/oauth2/token?{path}");
if (response.IsSuccessStatusCode)
{
Console.WriteLine("success");
token = await response.Content.ReadAsStringAsync();
}
else { Console.WriteLine($"failure: {response.StatusCode}"); }
return token;
}
You can see that I've tried it a couple of ways, including setting the client BaseAddress as well as just try to pass the url into the GetAsync method.
Anyone see what I'm doing wrong here?
UploadString is a POST method in the first example. In the second example a GET method is being done.
static async Task<string> GetAuthenticationTokenAsync() {
string token = string.Empty;
var clientId = ConfigurationManager.AppSettings["AuthNClientId"];
var uri = ConfigurationManager.AppSettings["AuthNUri"];
var userName = ConfigurationManager.AppSettings["AuthNUserName"];
var password = ConfigurationManager.AppSettings["AuthNPassword"];
var client = new HttpClient();
client.BaseAddress = new Uri(uri);
client.DefaultRequestHeaders.Accept.Clear();
var nameValueCollection = new Distionary<string, string>() {
{ "client_id", clientId },
{ "grant_type", "password" },
{ "username", userName },
{ "password", password },
};
var content = new FormUrlEncodedContent(nameValueCollection);
var response = await client.PostAsync("", content);
if (response.IsSuccessStatusCode) {
Console.WriteLine("success");
var json = await response.Content.ReadAsStringAsync();
dynamic authResult = JsonConvert.DeserializeObject(json);
token = authResult.access_token;
}
else { Console.WriteLine($"failure: {response.StatusCode}"); }
return token;
}

Paypal Rest Api With RestSharp not working in xamarin android

I have got error with RestSharp component when i am call Paypal Rest API.
I have the following code using Xamarin for Android.
public async Task<PayPalGetTokenResponse> GetAccessToken()
{
var restRequest = new RestRequest("/oauth2/token", Method.POST);
// Add headers
restRequest.AddHeader("Accept", "application/json");
restRequest.AddHeader("Accept-Language", "en_US");
// Make Authorization header
restClient.Authenticator = new HttpBasicAuthenticator(Config.ApiClientId, Config.ApiSecret);
// add data to send
restRequest.AddParameter("grant_type", "client_credentials");
var response = restClient.Execute<PayPalGetTokenResponse>(restRequest);
response.Data.DisplayError = CheckResponseStatus(response, HttpStatusCode.OK);
return response.Data;
}
But got error :"Error: SecureChannelFailure (The authentication or decryption has failed.)"
I have Also use ModernHttpClient but got same error
public async Task<PayPalGetTokenResponse> GetAccessToken()
{
string clientId = Config.ApiClientId;
string secret = Config.ApiSecret;
string oAuthCredentials = Convert.ToBase64String(Encoding.Default.GetBytes(clientId + ":" + secret));
string uriString = Config.ApiUrl+"/oauth2/token";
PayPalGetTokenResponse result;
HttpClient client = new HttpClient(new NativeMessageHandler());
var h_request = new HttpRequestMessage(HttpMethod.Post, uriString);
h_request.Headers.Authorization = new AuthenticationHeaderValue("Basic", oAuthCredentials);
h_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
h_request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en_US"));
h_request.Content = new StringContent("grant_type=client_credentials", UTF8Encoding.UTF8);
try
{
HttpResponseMessage response = await client.SendAsync(h_request);
//if call failed ErrorResponse created...simple class with response properties
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync();
var errResp = JsonConvert.DeserializeObject<string>(error);
//throw new PayPalException { error_name = errResp.name, details = errResp.details, message = errResp.message };
}
var success = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<PayPalGetTokenResponse>(success);
}
catch (Exception)
{
throw new HttpRequestException("Request to PayPal Service failed.");
}
return result;
}
Have you tried to force to modern day SSL protocol?
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
This works for me:
if (ServicePointManager.SecurityProtocol != SecurityProtocolType.Tls12)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var client = new RestClient(payPalURL) {
Encoding = Encoding.UTF8
};
var authRequest = new RestRequest("oauth2/token", Method.POST) {
RequestFormat = DataFormat.Json
};
client.Authenticator = new HttpBasicAuthenticator(clientId, secret);
authRequest.AddParameter("grant_type","client_credentials");
var authResponse = client.Execute(authRequest);

Categories

Resources