obtaining oauth_verifier from callback - c#

I have searched high and low for an answer to this problem. Basically, I am creating a C# application which (In it's first incarnation) will authenticate with the Projectplace API which uses OAuth 1.0a. It currently returns the oauth_verifier to the address bar, but when I use the var response = request.GetResponse(); method, it returns the oauth_token and oauth token_secret which I sent as part of the authorization in the first place.
Perhaps I am misunderstanding the way this process is supposed to work, but I've read every single answer out there and none seem to address this question. Do you have to, or is it possible, to pull the verifier code from the address bar (or wherever else it can be obtained), after I have entered my username and password on the authentication page after callback URL is loaded?
I believe OAuth1.0a requires the verification code to retrieve an access token, and I cannot find a simple way to pull the verification code.
I would really appreciate any help, it's driving me nuts!!
UPDATED 03.12.12
Thanks for your response!
Essentially, I am the client attempting to retrieve the oauth_verifier from the oauth provider after sending this initial request below, my next step is to authorize then retrieve verifier. I tried the following, hopefully as you suggested, like swimming in the deep end here :)
//Generate string for initiation request.
requestUri.AppendFormat("?oauth_consumer_key={0}&", consumerKey);
requestUri.AppendFormat("oauth_nonce={0}&", nonce);
requestUri.AppendFormat("oauth_timestamp={0}&", timeStamp);
requestUri.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
requestUri.AppendFormat("oauth_version={0}&", "1.0");
requestUri.AppendFormat("oauth_signature={0}", signature);
var request = (HttpWebRequest)WebRequest.Create(new Uri(requestUri.ToString()));
request.Method = WebRequestMethods.Http.Get;
var response = request.GetResponse();
var queryString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var parts = queryString.Split('&');
var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
var tokenSecret = parts[0].Substring(parts[0].IndexOf('=') + 1);
var queryString2 = String.Format("oauth_token={0}", token);
//AUTHORIZE WITH CREDENTIALS FROM USER.
var authorizeUrl = "https://api.projectplace.com/authorize?" + queryString;
Process.Start(authorizeUrl);`
//TRY AND READ VERIFICATION STRING AFTER AUTHORIZATION REDIRECT`
String oauthVerifier = HttpContext.Current.Request.QueryString["oauth_verifier"];
Unfortunately, once i've done this, I can't seem to get a querystring returned showing the oauth_verifier that I am clearly seeing in the string showing in the address bar. (Yes it's a very newbish way of describing it, i'm learning the code as well as OAuth :P).
Thanks for your help so far. I tried to run the above, but it just said that says "Object reference not set to an instance of an object.".
Also, if I attempt to use the previous code I used to obtain the querystring / response? from the initiation request using the following lines, the querystring3 just comes back as blank... really frustrating! :)
var queryString3 = new StreamReader(response.GetResponseStream()).ReadToEnd();
var parts3 = queryString3.Split('&');

I'm going to assume that by "in the address bar" you mean that the oauth_verifier is passed to your site from the ProjectPlace server via a query string parameter in the redirect URL. In order to read this in your C# server side code, you would use something like the following (I modified your sample code for this solution):
requestUri.AppendFormat("?oauth_consumer_key={0}&", consumerKey);
requestUri.AppendFormat("oauth_nonce={0}&", nonce);
requestUri.AppendFormat("oauth_timestamp={0}&", timeStamp);
requestUri.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
requestUri.AppendFormat("oauth_version={0}&", "1.0");
requestUri.AppendFormat("oauth_signature={0}", signature);
var request = (HttpWebRequest)WebRequest.Create(new Uri(requestUri.ToString()));
//Note: this is unnecessary - GET is the default
request.Method = WebRequestMethods.Http.Get;
//By casting to HttpWebResponse you get access to the QueryString property
var response = request.GetResponse() as HttpWebResponse;
var oauthVerifier = response.QueryString["oauth_verifier"];
//The response stream contains the HTTP response body,
//which will not contain the URL to which the redirect is sent
//I'm not sure if there is anything there that you will need
var responseBody = new StreamReader(response.GetResponseStream()).ReadToEnd();
//AUTHORIZE WITH CREDENTIALS FROM USER. -- Not sure what this section is doing
var queryString = string.Format("oauth_token={0}", oauthVerifier);
var authorizeUrl = "https://api.projectplace.com/authorize?" + queryString;
Process.Start(authorizeUrl);

Related

C# Asana POST new task returns error 400 (Bad request)

I have a problem with creating new task in Asana from my app.
Post method:
protected static T Post<T>(string route, object action = null, object parameters = null) where T : BaseResult, new()
{
var result = new T();
try
{
var actionUrl = GetActionUrl(route, action);
var request = (HttpWebRequest)WebRequest.Create(actionUrl);
request.Credentials = CredentialCache.DefaultCredentials;
request.Accept = "application/json";
request.Method = WebRequestMethods.Http.Post;
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
request.Headers.Add("Authorization: Bearer " + ApiKey);
if (parameters != null)
{
var contentJSON = JsonConvert.SerializeObject(parameters);
request.ContentType = "application/json";
using (var s = request.GetRequestStream())
using (var sw = new StreamWriter(s, Encoding.UTF8))
sw.Write(contentJSON);
}
var response = (HttpWebResponse) request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
var data = reader.ReadToEnd();
result = JsonConvert.DeserializeObject<T>(data);
}
}
catch (Exception ex)
{
result.IsOk = false;
result.Message = ex.GetMessage();
}
return result;
}
Action URL: https://app.asana.com/api/1.0/workspaces/MyWorkspace/tasks
JSON:{"data":{"name":"TestTask1","notes":"Test note","workspace":"*MyWorkspace*","assignee":"*MyAssignee"}}
But Asana returns me "The remote server returned an error: (400) Bad Request."
If I change request.ContentType to "application/x-www-form-urlencoded", I get no errors, but Asana returns me new task with empty fields.
What my next steps to fix issue should be?
Thank you
If you're using an ApiKey (and not a Personal Access Token), I believe that your Authorization Header should be
"Authorization: Basic " + EncodedAuthInfo
where
EncodedAuthInfo = Convert.ToBase64String(Encoding.Default.GetBytes(ApiKey + ":"))
See How do I connect to the Asana Rest API using c#? or the Using Basic Authentication section in https://asana.com/developers/documentation/getting-started/auth for details on using basic authentication.
I'm also a little confused by what you mean when you say that
JSON = {"data": {"name": "TestTask1"} ...
Is this the HTTP response that you expect?
Anyways, hopefully what I've outlined helps.
Hmm. I think I've got what's blocking you sorted out.
Imagine the scenario where you post to
https://app.asana.com/api/1.0/workspaces/123456/tasks
and you pass in the request body the parameter
"workspace":"789012"
What should the Asana platform do with this data? You've inadvertently specified the workspace twice with conflicting numbers. For this reason, you cannot specify the workspace id in the data when hitting an endpoint which also contains the workspace id in the URL.
The documentation is confusing on this point, because we don't clarify which parameters are found in the URL and which parameters are found in the JSON in the request body. I'm actually fixing this very soon! If this is indeed what's causing the issue, I'm sorry that we were not clear on this.
Personally, I think it might be a better user experience to allow the workspace to be duplicated in the parameter data if and only if it's identical to the one in the URL, but right now, we simply check to see that there is only one value for the workspace id. If there are more than one, even if they are the same one, we return the 400 error code.
You might consider parsing the response body, even on errors. In it, we try to provide fairly decent information about what was wrong about the request. For example, when testing my hunch about your request, what I got back was:
"errors":[{"message":"Duplicate field: workspace", ...}]
If we've done a good job about sending back informative messages, I hope you'll find this even more useful than an Asana sandbox! If this is not the issue, feel free to comment; I'll be happy to dive into this further.

How to make REST GET in Asp.net C#?

I can get an access token of Office 365. I can not make a REST request (GET) attaching this token in the header.
I'm using this code:
RestClient client = new RestClient();
client.EndPoint = #"https://outlook.office365.com/api/v1.0/me/folders/inbox/messages?$top=10";
client.Method = HttpVerb.GET;
client.ContentType = "application/json";
client.PostData = "authorization: Bearer " + myAccesToken.ToString();
String json = client.MakeRequest();
I've tested the access token in http://jwt.calebb.net and it's ok.
But it's always returning:
The remote server returned an error: (400) Bad Request.
I'm kind a knewby to REST and my english is not that good... Sorry! :)
(RE)EDIT
I've tried with RestSharp and I've simplified a bit my code...
Now I'm using my access token to make the GET request.
How do I add the "authorization bearer" to my request?
Is it like this?
//Ask for the token
var client = new RestClient("https://login.windows.net/common/oauth2/token");
var request = new RestRequest(Method.POST);
request.AddParameter("grant_type", "authorization_code");
request.AddParameter("code", Request.QueryString["code"]);
request.AddParameter("redirect_uri", myRedirectUri);
request.AddParameter("client_id", myClientID);
request.AddParameter("client_secret", myClientSecret);
IRestResponse response = client.Execute(request);
string content = "[" + response.Content + "]";
DataTable dadosToken = (DataTable)JsonConvert.DeserializeObject<DataTable>(content);
//I don't need a DataTable, but it was a way to retrieve my access token... :)
//Ask for info with the access token
var client2 = new RestClient("https://outlook.office365.com/api/v1.0/me");
var request2 = new RestRequest(Method.GET);
request2.AddHeader("authorization", myToken.ToString());
//I've tried this way also:
//client2.Authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator(dadosToken.Rows[0]["access_token"].ToString(), "Bearer");
IRestResponse response2 = client2.Execute(request2);
string content2 = "[" + response2.Content + "]";
Response.Write(content2); //this returns NOTHING!
Thanks again!
You can also use Fiddler to figure out if the Request is well formed.
Try a simpler endpoint first like: https://outlook.office365.com/api/v1.0/me
and check if the right data comes back. You can call this endpoint just from the browser and also look at the request/respond inside Fiddler.
The first thing to check: Is it a bad request. This usually means the method can't be found or the given parameters cannot be located. Check the deploy and make sure it is the most up to date version and also check that your server is actually running.

Paypal PDT returns Fail always to my HTTP post request C# MVC

I am facing very weird kind of problem that after successful payment transaction, I am not able to get TransactionId appended with returningUrl. Since Paypal auto redirects me to my ReturnUrl which I have mentioned in PDT settings page, and Paypal appends the trasactionId to this returningUrl named tx and using that trasactionId I make a Post request to this Url
https://www.sandbox.paypal.com/cgi-bin/webscr
But here is the problem that I am not able to get that transactionId? what could be the problem kindly any body help me in this issue. This is my code that I am using to make an HTTP post request.
string authTokenTest = "sMfRi9rJN3AjqsejnMxFfkeIwhwrCmVZz3nplUy9V6a9Yq0_2YdugSvZYNa";
//used this but could not retrieved "tx"
//string txToken = Request.QueryString.Get("tx");
//Then used this but no use
var queryValues = HttpUtility.ParseQueryString(Request.Url.Query);
var txToken = queryValues["tx"];
string query = string.Format("cmd=_notify-synch&tx={0}&at={1}", txToken, authTokenTest);
//// Create the request back
string strSandbox = "https://www.sandbox.paypal.com/cgi-bin/webscr";
string url = strSandbox;
/// to use HTTP 1.1 and TLS 1.2
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
ServicePointManager.DefaultConnectionLimit = 9999;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
// Set values for the request back
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = query.Length;
// Write the request back IPN strings
StreamWriter stOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII);
stOut.Write(query);
stOut.Close();
// Do the request to PayPal and get the response
HttpWebResponse payResp = (HttpWebResponse)req.GetResponse();
StreamReader sr = new StreamReader(payResp.GetResponseStream());
string strResponse = sr.ReadToEnd();
sr.Close();
If I make a direct request to this URL via browser and append a TransactionId and IdentityToken then I get the success response, but in this way I am not getting any way the transactionId and my Response is always Fail. Kindly help my in this problem. What could be the issue in my code or any other problem to resolve this issue. Thanks for your time.
I use MVC and so use model binding to get the tx value from the query string. But I don't think that's your problem.
The Return URL has to be set, as you said you did. Also PDT has to be turned on in the same place the URL is specified. Also, unfortunately, customers will not be returned automatically to your site if they use a credit card instead of a PayPal account.
I'm implementing IPN though because credit card customers may not return to the site.

RestSharp - Retrieving Authorization token from POSTed response

I am trying to pass username and password to the following URL :
https://maxcvservices.dnb.com/rest/Authentication
According to the documentation the user_id and password must be passed as headers with the keys: x-dnb-user, x-dnb-pwd respectively.
I thus far have the following code which seems to work but I am unable to retrieve the auth token returned by the response object:
public static void Main (string[] args)
{
var client = new RestClient ("https://maxcvservices.dnb.com/rest/Authentication");
var request = new RestRequest (Method.POST);
request.AddHeader("x-dnb-user", myEmail);
request.AddHeader("x-dnb-pwd", myPassword);
IRestResponse resp = client.Execute(request);
var content = resp.Content;
Console.WriteLine (resp.StatusDescription);
Console.WriteLine (resp.StatusCode);
}
When I try printing the content I get a blank line but what I am actually expecting is the auth token that is returned by the service. A couple of things I think I am doing in the code (but not sure), is passing the userid and password as headers in the POST request which is what is required. The token is returned as the value of the 'Authorization' field in the response object. I was wondering how I might print the token. Also the statusDescription,statusCode both print OK which tells me I have the correct request but am unable to locate the auth token in the response. Any help would be much appreciated in guiding me on how to access the auth token in the Authorization field of the returned POST response.
So you're trying to get the HttpHeader values for Authorization from the IRestResponse object?
You could use e.g. use LINQ for that:
var authroizationHeaderFromResponse = resp.Headers.FirstOrDefault(h => h.Name == "Authorization");
if (authroizationHeaderFromResponse != null)
{
Console.WriteLine(authroizationHeaderFromResponse.Value);
}
Which yields
INVALID CREDENTIALS
You assume that if the response status code is 200 - OK, then there must be a response body accompanying it.
Does the documentation specifically state that you should expect a token in the response body in return?
The D&B developers could send a 200 - OK response with no response body if they want, or they can add their serialized token (JSON, XML etc) elsewhere, e.g. in a header field.
An example of this can be seen in this code from an ASP.NET Web API returning a response from a successful PUT
if (result.Success)
{
var dto = Mapper.Map<TEntity, TDto>(result.Data as TEntity);
var response = Request.CreateResponse(HttpStatusCode.Created, dto);
var uri = Url.Link("DefaultApi", new {id = dto.Id});
response.Headers.Location = new Uri(uri);
return response;
}
This would return a 200 - OK with a serialized object (result.Data) in the response body, but there's nothing wrong with me changing the following
var response = Request.CreateResponse(HttpStatusCode.Created, dto);
To something like
var response = Request.CreateResponse(HttpStatusCode.Created);
That way you would still get a 200 - OK response, but without a response body. This of course is against the recommendations of the HTTP/1.1 Standard for PUT verbs, but it would still work.
I could even do this for giggles
throw new HttpResponseException(HttpStatusCode.Created);
And you would still get a 200 - OK response. Somewhat evil, but possible.
I would suggest trying to fetching data from another resource with the x-dnb-user and x-dnb-pwd header fields set, and check if a response body is returned then. Perhaps D&B was inspired by Basic Authentication when implementing these header fields, and as such require them to be present in every request?
It's worth a try.
Let me know how that works out.
Look in the Headers collection of IRestResponse. It will probably be there rather than the content.
Hth
Oli
It could be that the AUTHTOKEN comes back with the cookies, as this is a common approach.
In this case, you'll need to attach a CookieContanier to your IRestClient, then this container will store the cookies. Provided you use the same client for subsequent requests, that auth cookie will let you in.
private CookieContainer _cookieJar;
...
_cookieJar = new CookieContainer();
_client.CookieContainer = _cookieJar;
You can then inspect the container after a request
_client.PostAsync(MyRequest, (r, h) =>
{
r.Cookies... // inspect em

LinkedIn - How to get access token?

I'm trying to get access token from LinkedIn.
I'm follwing this URL https://developer.linkedin.com/documents/authentication
I am able to get an authorization code.
But when I'm passing the authorization code to this URL
https://www.linkedin.com/uas/oauth2/accessToken?grant_type=authorization_code &code=AUTHORIZATION_CODE &redirect_uri=YOUR_REDIRECT_URI &client_id=YOUR_API_KEY &client_secret=YOUR_SECRET_KEY
I get an error in the below format
{"error":"invalid_request","error_description":"missing required parameters, includes an invalid parameter value, parameter more then once. : Unable to retrieve access token : appId or redirect uri does not match authorization code or authorization code expired"}
Any ideas? Thanks in advance.
This is because authorization code expires in 20 seconds. So you have to get the Access Token within that time frame.
I got the same error as you. I also met the following conditions:
My request was a POST request.
My redirect_uri's were the same in /authorization and /accessToken calls.
The /accessToken call was executed immediately after receiving the authorization code, so
it wouldn't expire.
What finally did the trick for me was revoking the access token generated on the application details page on https://www.linkedin.com/secure/developer.
This is an access token for oAuth 1.a and is not compatible with oAuth 2.0 on which the linkedIn api is currently running.
After revoking this access token I was able to get a new one with the /authorization and /accessToken calls.
I see this is an older thread, however if it will help anyone, here is my working solution, working on MVC core 2.0 as of december 2018:
first, redirect to LinkedIn like this
var url = "https://" + Request.Host + "/Login/LoginLinkedIn";
url = WebUtility.UrlEncode(url);
var redirectLinkedIn = "https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=*ClientId*&client_secret=*ClientSecret*&redirect_uri=" + url + "&state=*random required nummeric value*";
return Redirect(redirectLinkedIn);
after that, you will receive the answer in your Login/LoginLinkedIn action (don't forget to specify this path in your app settings Authorized Redirect URLs).
There you will use this private method to get a dynamic object filled with user data
private dynamic GetLinkedInUser(string code)
{
dynamic jresult;
NameValueCollection parameters = new NameValueCollection {
{"client_id", *ClientId*},
{"client_secret", *ClientSecret*},
{"grant_type", "authorization_code"},
{"redirect_uri", "https://" + Request.Host + "/Login/LoginLinkedIn"},
{"code", code}
};
WebClient client = new WebClient();
byte[] result = client.UploadValues("https://www.linkedin.com/oauth/v2/accessToken", "POST", parameters);
string response = System.Text.Encoding.Default.GetString(result);
string accessToken = JsonConvert.DeserializeObject<dynamic>(response).access_token;
WebRequest webReq = WebRequest.Create("https://api.linkedin.com/v1/people/~:(id,email-address,first-name,last-name)?format=json");
webReq.Method = "GET";
webReq.Headers.Add("Authorization","Bearer "+accessToken);
HttpWebResponse webResponse = (HttpWebResponse)webReq.GetResponse();
using (StreamReader reader = new StreamReader(webResponse.GetResponseStream())) {
string objText = reader.ReadToEnd();
jresult = JsonConvert.DeserializeObject<dynamic>(objText);
}
return jresult;
}
hope it helps someone :)

Categories

Resources