LinkedIn API with LUCEE


#1

Hi,

I’m “playing” with LinkedIn API.

The first step is naturally to be able to log into LinkedIn via its authorization requirements.

According to its doc, it’s the following URL plus parameters:

URL parameters:

client_id 
client_secret
redirect_uri
response_type
state

I have valid values for all the parameters.

If I run the URL with parameters and their respective values by hand, it works as expected, however, when I put the above URL with parameters and values into a variable, and with username and password for the CFHTTP call, it prompts for username and password.

I wonder if any of you have experienced the same, and how did you overcome it?

Thanks in advance.

P.S. It would be nice to be able to add new category such as LinkedIn or API etc…


#2

There is a long-standing bug with cfhttp which prevents the username and password attributes being sent over HTTPS:

https://luceeserver.atlassian.net/browse/LDEV-95

Try using cfhttpparam to send the authorization header as described in that bug report.


#3

This is how I attempt to bypass the bug as you suggested except that (values for the username and password etc. posted here are not authentic).

<!---
<cfhttpparam type="header" name="username" value="donli@myemail.com">
<cfhttpparam type="header" name="password" value="donliPWD">
--->

<cfhttpparam type="header" name="Authorization" value="Basic #ToBase64('donli@myemail.com:donliPWD')#">

Outcome:

METHOD=“POST”
403 Forbidden
Unauthorized

METHOD=“GET”
(1) if output cfhttp.statusCode only, it’s 200 (looking good),
however, if added, cfhttp.fileContent,
it asked for username and password

I’m a bit puzzled here.

Thanks.


#4

I haven’t used the LinkedIn API before, but I think you may be misunderstanding the authorization/authentication process. According to the docs, the URL you’re trying to call is for your users to visit so that they can grant your app the permissions it needs. You should send them there via a cflocation with the appropriate url parameters, rather than cfhttp.

Once they’ve granted permission (Step 2 in the docs), you’ll need cfhttp to make a POST request to the API and get your access token (Step 3). Once you have that, you’ll be able to make authenticated calls (Step 4) also using cfhttp.

A username/password doesn’t seem to be needed at any stage.


#5

Very helpful. At step 3, once I return results such as
{"access_token":"AQUzDl3Wx752b6CJGuGgkiskdMnDD30Ra2oMdT7sC8mCvDd3DXIQulj7AEgFTVFhVlkV2MTtn3An6jntg_ikGKTVhjgeJLWUeh4WmQeYuqMqzlh6er2R7DumVEstXTY8-7Ix0bo4-u8siq5TwrOa-pSv2Z9bIENMutjzAkjdgrnmocj0ov0FMg","expires_in":5283999}

How can we extract the access_token value and expires_in value out of it?

The output looks like an array, thus, I attempted #cfhttp.fileContent["access_token"]#, but it looks like #cfhttp.filecontent# is complex string. What’s a good way to get these two values and we move to next step?

Many thanks.


#6

Try:

result = DeserializeJSON( cfhttp.fileContent );
access_token = result.access_token;

#7

Awesome. It’s working now. Many thanks!


#8

LinkedIn API is a tough nut to crack. I’m now attempting to test its “Share” feature.

The following code generated “405 Method Not Allowed”. Why? How could we fix it? Many thanks.

<cfset stuff = {
  "comment": "Test posting: check out developer.linkedin.com!",
  "content": {
	"title": "Test posting a title",
    "description": "Test posting to LinkedIn via LinkedIn's API !"
  },
  "visibility": {
    "code": "anyone"
  }  
}>
	
<cfhttp url="https://api.linkedin.com/v1/people/~/shares?format=json" method="post">
	<cfhttpparam type="header" name="Authorization" value="Bearer #access_token#">
	<cfhttpparam type="header" name="Content-Type" value="application/json">
	<cfhttpparam type="body" value='#serializeJSON(stuff)#'>
</cfhttp>

<cfoutput>
#cfhttp.statusCode# <br>
</cfoutput>

#9

When posting JSON rather than XML, it seems you need to send this header in addition to the Content-Type:

<cfhttpparam type="header" name="x-li-format" value="json">

#10

Good thought, Julian, I’ve added this cfhttpparam line right under the “Content-Type” one,
and yet, still same error of "405 Method Not Allowed ". Thanks.


#11

In addition, I have w_share permission (I assume it would suffice to share a post or a comment something).


#12

I used LinkedIn API console, able to send a share via POST. Here’s the console output for the request (except the access_token value for security):

POST /v1/people/~/shares?oauth2_access_token=AQXy288jskskdjsjsdssfy5ypKcBkdb_LKo43oTBR-1sMktFyQJZYfOd1gfFW8gkhAXnSZDjBu-C8yMZ5VS83-51CDlntGreiDDJylEIGkmZIDkkdp5mJdDV_-MF8nrcPEXqE1_IXI1p77_O1NWTmM20GDV8ytZYWlKA58Vl6_nOzJBFyvgMps-NW99qMaHT-3M&format=json HTTP/1.1
x-li-format:json
Host:api.linkedin.com
Content-Length: 356
X-Target-URI:https://api.linkedin.com
Connection:Keep-Alive
Content-Type:application/json

{
  "comment": "Check out developer.linkedin.com!",
  "content":  {
    "title": "LinkedIn Developers Resources",
    "description": "Leverage LinkedIn's APIs to maximize engagement",
    "submitted-url": "https://developer.linkedin.com",
    "submitted-image-url": "https://example.com/logo.png"
  },
  "visibility":  {
    "code": "anyone"
  }
}

Based on the above, so, I’ve revised the code accordingly, specifically as follows (var stuff has been defined and we have the #access_token# as well of course):

<cfhttp url="https://api.linkedin.com/v1/people/~/shares?oauth2_access_token=#access_token#&format=json" method="POST">
	<cfhttpparam type="header" name="Content-Type" value="application/json">
	<cfhttpparam type="header" name="x-li-format" value="json">
	<cfhttpparam type="body" value='#serializeJSON(stuff)#'>
</cfhttp>

And yet, we still have the same error of “405 Method Not Allowed”. It’s mind-boggling. Thanks.


#13

The error suggests a problem with the request method, but it’s definitely POST in the docs, and the content type headers seem fine. You are missing the “submitted-url” and “submitted-image-url” values from your share data, but unlikely that would cause the error. Does the reponse include a more detailed “message” field of any kind?


#14

Here’s the response, and method-wise, only POST or PUT would make sense, I’ve tried both with the same error, thanks.

HTTP/1.1 201 Created
x-li-format:
json
X-LI-Proto:
http/1.1
X-LI-UUID:
UMPPZlpOzBRA9c3nISsAAA==
X-Li-Fabric:
prod-ltx1
x-li-request-id:
SAJMRC8T95
Location:
https://api.linkedin.com/v1/pal/people/~/network/updates/key=UPDATE-12717617-6285831129270403072
Set-Cookie:
lidc=&quot;b=TB17:g=1033:u=758:i=1498658926:t=1498740274:s=AQFGPujEGGvyzkcdr9nuUuC8RFPbbZqs&quot;
X-LI-Route-Key:
&quot;b=TB17:g=1033:u=758:i=1498658926:t=1498740274:s=AQFGPujEGGvyzkcdr9nuUuC8RFPbbZqs&quot;
X-Li-Pop:
prod-edc2
Connection:
keep-alive
Server:
Apache-Coyote/1.1
Date:
Wed, 28 Jun 2017 14:08:46 GMT
Transfer-Encoding:
chunked
Vary:
*
Content-Type:
application/json;charset=UTF-8

{
  "updateKey": "UPDATE-12717617-6285831129270403072",
  "updateUrl": "https://www.linkedin.com/updates?discuss=&scope=12717617&stype=M&topic=6285831129270403072&type=U&a=qEWY"
}

#15

Are you sure that’s the right response? You said it was a 405?


#16

Sorry I wasn’t clear, that response with 201 was from the LInkedIn API console.


#17

After some offline discussion, it seems the issue is with the way Lucee encodes the url in cfhttp by default which was causing the tilde character (~) in the LinkedIn endpoint not to be recognized.

The fix is just to add encodeUrl=false to the cfhttp tag like so:

<cfhttp url="https://api.linkedin.com/v1/people/~/shares?format=json" method="POST" encodeUrl=false>
	<cfhttpparam type="header" name="Authorization" value="Bearer #access_token#">
	<cfhttpparam type="header" name="Content-Type" value="application/json">
	<cfhttpparam type="header" name="x-li-format" value="json">
	<cfhttpparam type="body" value='#serializeJSON(stuff)#'>
</cfhttp>

#18

Great work, Julian, much appreciated!


#19

Hi Julian, I wonder if you have some contact at Linked API because I’d like to find out if it’s API is able to let one retrieve update of anyone on the LinkedIn (with his/her user id). I’ve googled for answers and stackoverflow as well, however, to no avail. Thus, only their own API engineer would know.
Many thanks.
Don


#20

Sorry, Don. I’ve never even used LinkedIn or its API, let alone have any contacts there.