LinkedIn - How to get access token? - c#

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 :)

Related

How to send the BreezeSession's value with each of requests to Adobe Connect's Web Service?

I have read the Adobe Connect's document, I could not understand that where should I place my BreezeSession's value (especially in Postman) when I want to call other actions which need authentication and BreezSession's value to work.
Step 1: User can login with his username and password with this GET action:
$"{AdobeConnectServerURL}/api/xml?action=login" +
$"&login={login.Username}" +
$"&password={login.Password}";
The code, results BreezeSession's value in its header. So my authentication and login works perfectly.
Now imagine I want to call another Adobe Connect's action which creates a new meeting, I have to create the meeting with an authorized user's BreezeSession.
How can I send the BreezeSession's value among create-user's action to Adobe Connect Server ?
I found the answer I hope that it will be helpful for others.
Inside the URL you can use the segment named session:
YourURLHere/api/xml?session=YourBreezeSession&action=YourActionHere
or you can set cookie using this function inside your code for calling APIs.
public async Task<string> CallApi(string apiUrl)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(apiUrl);
var cc = new CookieContainer();
cc.Add(new Cookie("BREEZESESSION", "Your BreezeSession Value Here", "/", "your URL"));
request.CookieContainer = cc;
var response = await request.GetResponseAsync();
var x = new StreamReader(response.GetResponseStream()).ReadToEnd();
return x;
}

c# RestSharp: Adding and delete cookie because Statuscode 403

i am currently try to get information of an external API using RestSharp (Version 107.1.2). Unfortunately, in every request I get response Status Code 403 "Forbidden". I now have contact to the provider and he told me, to delete all cookies first and then add the cookie "SMCHALLENGE=YES".
I tried this in RestSharp, but when using the client.AddCookie extension, I receive ArgumentException. I now found another option, to add the cookie in header, but this doesn't work either.
Do you have an idea, how to delete all cookies and then add the SMCHALLENGE cookie?
var client = new RestClient("https://test.de/api/token");
string resource = null;
client.Authenticator = new HttpBasicAuthenticator("testUser", "testPW");
string apiKey = null;
var request = new RestRequest(resource, Method.Get);
//Following execution throws System.ArgumentException: "The {0} parameter cannot be an empty string. Parameter name: cookie.domain"
//client.AddCookie("SMCHALLENGE", "YES");
request.AddHeader("Cookie", "SMCHALLENGE=YES");
var response = client.ExecuteAsync(request);
response.Wait();
RestResponse rr = response.Result;
Thank you very much!
Cookies aren't headers. You need to add your cookies to the RestClient own cookie container. Cookies that are returned in the response will also be available in the cookie container. There's a function on RestClient to do that as a shortcut.
var client = new RestClient("https://test.de/api/token");
client.AddCookie("SMCHALLENGE", "YES");
You can also work with the cookie container:
client.CookieContainer.Add(new Cookie(...));
You'd need to avoid creating a new RestClient instance for each request. This way you'd also keep the cookies across requests.

LinkedIn API failed to connect when trying to get companies informations

When I try to get profile information, using HttpWebRequest, it works perfectly, it returns the response I need.
But when I try to get company informations, the LinkedIn web service returns the following error.
{ "errorCode": 0,
"message": "Unknown authentication scheme",
"requestId": [RequestID],
"status": 401,
"timestamp": 1479383163405 }
I used the same access token in both queries. And I can't figure why I have a failed authentication in the second query.
There are the 2 functions :
//Get profile :
private void GetPeopleProfile(string accessToken) {
var peopleUrl = String.Format("https://api.linkedin.com/v1/people/~?oauth2_access_token={0}&format=json",accessToken);
HttpWebRequest webRequest = WebRequest.Create(peopleUrl) as HttpWebRequest;
StreamReader responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
string responseData = responseReader.ReadToEnd();
JObject updates = JObject.Parse(responseData);
responseReader.Close();
webRequest.GetResponse().Close();
}
//Get profile's Company :
private void GetUserCompanies(string accessToken){
var copaniesUrl = String.Format("https://api.linkedin.com/v1/companies?format=json&is-company-admin=true?oauth2_access_token={0}&format=json", accessToken);
HttpWebRequest webRequest = WebRequest.Create(copaniesUrl) as HttpWebRequest;
StreamReader responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
string responseData = responseReader.ReadToEnd();
JObject updates = JObject.Parse(responseData);
responseReader.Close();
webRequest.GetResponse().Close();
}
Maybe wrong URL?
Parameters separators are wrong here (two ? in a URL seems wrong, you are also repeating format=json) :
"https://api.linkedin.com/v1/companies?format=json&is-company-admin=true?oauth2_access_token={0}&format=json"
This looks better:
"https://api.linkedin.com/v1/companies?format=json&is-company-admin=true&oauth2_access_token={0}"
You can try the REST api here without your code noise.
It seems that the Linkedin API now expects an authorization HTTP header instead of a querystring parameter oauth2_access_token.
This is accomplished by including an "Authorization" header in your HTTP call to LinkedIn's API.
https://developer.linkedin.com/docs/oauth2
Try this and remove the access token from the querystring:
webRequest Headers.Add("Authorization", "Bearer " + accessToken);

Insert photo ERROR: The remote server returned an error: (403) Forbidden

I need your help!.
Im trying to insert a new photo into a Picasa Album using Oauth 2.0 and a simple HttpRequest process. The result is that I cant insert a new photo into my Picasa web album after following the instructions listed on: https://developers.google.com/picasa-web/docs/2.0/developers_guide_protocol#Auth
I also have to say that I tried using the .Net library that they provide with the same results.
The implementation that I'm using now is the following:
public static string PostImage(
string streamImageConvertedToString)
{
string url = string.Format("https://picasaweb.google.com/data/feed/api/user/{0}/albumid/{1}", "username#gmail.com", "idAlbum");
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.ContentType = "image/jpeg";
request.ContentLength = Encoding.UTF8.GetByteCount(data);
request.Method = "POST";
request.Headers.Add("GData-Version", "2");
request.Headers.Add("Slug", "cute_baby_kitten.jpg");
request.Headers.Add("Authorization", "Bearer " + GetToken());
if (data != null)
{
using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
{
writer.Write(data);
}
}
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
string result = string.Empty;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
return result;
}
private static string GetToken() {
const string ServiceAccountEmail = "someid#developer.gserviceaccount.com";
var servicio = new PicasaService(null);
var certificate = new X509Certificate2(HttpContext.Current.Server.MapPath("/key2.p12"), "notasecret", X509KeyStorageFlags.Exportable);
var serviceAccountCredentialInitializer =
new ServiceAccountCredential.Initializer(ServiceAccountEmail)
{
Scopes = new[] { "https://picasaweb.google.com/data/" }
}.FromCertificate(certificate);
var credential = new ServiceAccountCredential(serviceAccountCredentialInitializer);
if (!credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Result)
throw new InvalidOperationException("Access token request failed.");
return credential.Token.AccessToken;
}
Any help is welcome!!
(403) Forbidden
Means that you are trying to use a method insert which requires authorization to do.
you are connecting to service account someid#developer.gserviceaccount.com which should give you access to someid#developer.gserviceaccount.com pictures then.
you appear to be trying to access username#gmail.com unless you have given someid#developer.gserviceaccount.com access to insert pictures on behalf of username#gmail.com (Which I am not even sure is possible) you are not going to have permission to do this.
Remember a service account is a sudo user it has its own drive account, calendar account ... it does not have access to a random users data unless that user has given them access like they would any other user.
Note: Google .net client library does not support gdata APIs. Picasa is a gdata library I like how are trying to merge the two I am have to test this.
You're best (imho) approach would be to forget libraries and forget service accounts. Get a refresh token for the google user account you're trying to insert to, and use the raw HTTP REST API to invoke Picasa.

obtaining oauth_verifier from callback

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);

Categories

Resources