out of network API calls returning "unauthorized" error

14 posts / 0 new
Last post
Julia Ma's picture
Joined: 10/20/2011
Thu, 02/23/2012 - 08:45
out of network API calls returning "unauthorized" error

I'm trying to access out-of-network profiles using the API: https://developer.linkedin.com/documents/accessing-out-network-profiles
I'm writing my code in Python.

As I understand it, I just add an extra header to my HTTPSConnection request:

normal call:
connection.request(method, relative_url, body = body, headers={'Authorization': OAuth_header})

out-of-network call:
name = x-li-auth-token # these values were extracted from the http-header I received
value = name:R8Y4
connection.request(method, relative_url, body = body, headers={'Authorization': OAuth_header, name: value})

When I do the out-of-network call, I get an error:
<error>
<status>401</status>
<timestamp>1330027911625</timestamp>
<request-id>VHUSL0J7TL</request-id>
<error-code>0</error-code>
<message>[unauthorized]. OAU:k1tofeoqr4id|2dc38f4e-73d1-4d31-9330-dd82aca89616|*01|*01:1330027911:CRc7YYYQRe2VS6woJpGX+qYVa/Q=</message>
</error>

I've been testing this on both my own profile and an actual out-of-network profile, no change in error.
From various API requests, the "value" changes slightly, and I have tried all variants:
"name:R8Y4"
"search-name:R8Y4"
"OUT_OF_NETWORK:R8Y4"

Does anyone know what I'm doing wrong? Please help! Thank you.

Steven Citron-Pousty's picture
Joined: 08/02/2011
Thu, 02/23/2012 - 14:01

Greetings Julia:
There is a limited set of fields you can request for an out of network profile. If you call for a field you can't get you may get the 401 error. Try reducing the number of fields requested and see if you get rid of the error.
Thanks
Steve

Julia Ma's picture
Joined: 10/20/2011
Thu, 02/23/2012 - 14:15

Thanks Steve! I have tried reducing the request to just an 'id' but still an error.
Not sure if this helps, but I've also tried the request on my own profile and yet getting the same [unauthorized] error.

Just to be clear, the additional header should be separate, not included in the Authorization header, right? I've tried both ways (same error) but I just want to make sure I'm eliminating all possible bugs.

Steven Citron-Pousty's picture
Joined: 08/02/2011
Thu, 02/23/2012 - 14:19

Hey Julia:
Are you using the python library found on this page?
https://developer.linkedin.com/documents/libraries-and-tools

Julia Ma's picture
Joined: 10/20/2011
Thu, 02/23/2012 - 14:35

I am using the very last listed Python one on that page, written by Ozgur. I have added some functionality to his library, and trying to add the ability to see out-of-network profiles. All other API calls are working fine. The issue lies with the additional header that the API requests.

Steven Citron-Pousty's picture
Joined: 08/02/2011
Thu, 02/23/2012 - 14:39

Beyond my level of expertise - sending on to our Python experts

Kirsten Jones's picture
Joined: 06/30/2011
Thu, 02/23/2012 - 14:51

Can you provide the following so we can help troubleshoot:
* Original request to get the profile ID and auth headers
* The full response for that (including the auth info)
* Subsequent request using the auth info, including all headers
* Full response (including headers) from the server

You can get this using Fiddler or HttpScoop using the strategies on Debugging API Calls

Note that we suggest a particular oauth library (in this case python's oauth2) because it's known to work correctly and there are edge cases (this may be one) where other libraries may fail to sign or pass along requests correctly. That having been said, I should be able to make a correct call using oauth2 and compare it if you provide the above.

Julia Ma's picture
Joined: 10/20/2011
Thu, 02/23/2012 - 16:48

I have uploaded the library I am using (it's the python-linkedin library with a few extra implementations, including this buggy OON call) to here:
http://web.media.mit.edu/~juliama/linkedin2.py

Using Python from the command line, these are the Oauth steps:
import linkedin2
RETURN_URL = 'http://localhost'
KEY = '####'
SECRET = '####'
api = linkedin2.LinkedIn(KEY, SECRET, RETURN_URL)
api.request_token()
api.get_authorize_url()
api.access_token(verifier = '#####')

Then I do a company search on Schneider Electric (chosen because all of these profiles are out of my network). I have hard-coded some things while trying to debug this, so the get_search() method automatically requests the "api-standard-profile-request" field:
api.get_search({'company-name': 'schneider electric', 'count':1})
This is equivalent to a URL call:
/v1/people-search:(people:(id,api-standard-profile-request),num-results)?company-name=schneider%20electric&count=1
The actual HTTP request is done in linkedin2.py line 948, with the headers field:
headers={'Authorization':header}

Response:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<people-search>
<people total="700" count="1" start="0">
<person>
<id>xwAw1s9fJ5</id>
<api-standard-profile-request>
<url>http://api.linkedin.com/v1/people/xwAw1s9fJ5</url>
<headers total="1">
<http-header>
<name>x-li-auth-token</name>
<value>OUT_OF_NETWORK:Hhmg</value>
</http-header>
</headers>
</api-standard-profile-request>
</person>
</people>
<num-results>43314</num-results>
</people-search>

Now I have the ID and header I need to make an out-of-network call.
api.get_profile_OON('xwAw1s9fJ5')
This method (as it is written right now) does the profile request again because eventually I want to be able to call get_profile() and have the code figure out if it's out of network. Either way, the "value" part of the http-header just changes from "OUT_OF_NETWORK:Hhmg" to "name:NhGo". I have tried both "value"s with the same error.
The get_profile_OON() method is equivalent to this call:
/v1/people/xwAw1s9fJ5
with the actual HTTPS request being made in linkedin2.py line 907, with the headers field:
headers={'Authorization':header, name:value}

The response from this get_profile_OON() call is:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<error>
<status>401</status>
<timestamp>1330043975706</timestamp>
<request-id>5X8IV87R3R</request-id>
<error-code>0</error-code>
<message>[unauthorized]. OAU:k1tofeoqr4id|2dc38f4e-73d1-4d31-9330-dd82aca89616|*01|*01:1330043975:06GACUl1IjtFJTeOqEY5IuJNdKc=</message>
</error>

Hope all of that was clear and helps. Please let me know if I can clarify anything! Thanks :)

Kirsten Jones's picture
Joined: 06/30/2011
Fri, 02/24/2012 - 07:49

I'm not sure why your call is failing. Here's the sequence using the tested oauth2 library in python, including the entire HTTP conversation.

First, do the search:
http://api.linkedin.com/v1/people-search:(people:(distance,id,first-name,last-name,headline,api-standard-profile-request))

Parameters (I'm using OAuth in the parameters for this call)
oauth_body_hash=2jmj7l5rSw0yVb%2FvlWAYkK%2FYBwk%3D
oauth_nonce=41358038
oauth_timestamp=1330098205
oauth_consumer_key=xxx
oauth_signature_method=HMAC-SHA1
facet=network%2CO
oauth_version=1.0
oauth_token=xxx
keywords=Schneider+Electric
oauth_signature=xxx

Response includes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   <person>
      <distance>-1</distance>
      <id>UBAQYFeiHo</id>
      <first-name></first-name>
      <last-name>Private</last-name>
      <headline>Assistant Engineer at Schneider Electric</headline>
      <api-standard-profile-request>
        <url>http://api.linkedin.com/v1/people/UBAQYFeiHo</url>
        <headers total="1">
          <http-header>
            <name>x-li-auth-token</name>
            <value>OUT_OF_NETWORK:wHti</value>
          </http-header>
        </headers>
      </api-standard-profile-request>
    </person>

Second call, to get the profile:
http://api.linkedin.com/v1/people/UBAQYFeiHo:(id,first-name,last-name)

Request headers:
Host: api.linkedin.com
x-li-auth-token: OUT_OF_NETWORK:wHti
accept-encoding: gzip, deflate
user-agent: Python-httplib2/$Rev$

Response:
{'status': '200', 'content-length': '158', 'content-location': u'http://api.linkedin.com/v1/people/UBAQYFeiHo:(id,first-name,last-name)?oauth_body_hash=2jmj7l5rSw0yVb%2FvlWAYkK%2FYBwk%3D&oauth_nonce=27886786&oauth_timestamp=1330098212&oauth_consumer_key=xxx&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_token=xxx&oauth_signature=xxx', 'transfer-encoding': 'chunked', 'vary': '*', 'server': 'Apache-Coyote/1.1', '-content-encoding': 'gzip', 'date': 'Fri, 24 Feb 2012 15:43:34 GMT', 'x-li-request-id': 'N368G241EA', 'x-li-format': 'xml', 'content-type': 'text/xml;charset=UTF-8'}

UBAQYFeiHo

Private

The python code to make the second part work with the oauth2 library is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import oauth2 as oauth
import time
 
url = "http://api.linkedin.com/v1/people/UBAQYFeiHo:(id,first-name,last-name)"
consumer = oauth.Consumer(
        key="xxx",
        secret="xxx")
        
token = oauth.Token(
        key="xxx", 
        secret="xxx")
 
client = oauth.Client(consumer, token)
 
resp, content = client.request(url, headers={'x-li-auth-token':'OUT_OF_NETWORK:wHti'})
print resp
print content
Karthik Dinakar's picture
Joined: 12/07/2011
Sat, 02/25/2012 - 16:09

Hi,

I tried doing the same thing that has been done above using the httplib2 library:

mport httplib2
http = httplib2.Http()

url = 'http://api.linkedin.com/v1/people/UBAQYFeiHo'

import urllib
params = None

response, content = http.request(url, 'GET', params,
headers={'x-li-auth-token': 'OUT_OF_NETWORK:wHti'}
)

print response
print content

I get this in return:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<error>
<status>401</status>
<timestamp>1330214399769</timestamp>
<request-id>QXG9EBADPP</request-id>
<error-code>0</error-code>
<message>Unknown authentication scheme</message>
</error>

Is the oauth2 library you are using doing something in particular for this api to access OON profiles?

Thanks so much!!!!

Kd

Kirsten Jones's picture
Joined: 06/30/2011
Mon, 02/27/2012 - 07:21

Karthik,

Our API uses OAuth. httplib2 does not create the correct headers to sign the request for oauth. You need to use an oauth library to sign your requests or they will not be authorized for our system. I encourage you to work through the Quick Start Guide to learn how to make requests using our API.

Julia Ma's picture
Joined: 10/20/2011
Mon, 02/27/2012 - 14:12

Hi Kirsten,
Thank you so much for your response!! I have switched over to the oauth2 library and it looks like out-of-network calls are finally working :)
I really appreciate your help,
Julia

steven_persona jackson_persona's picture
Joined: 11/11/2011
Tue, 02/28/2012 - 19:30

Hi,

i have got the following error when send invitation using php
==============================================
when i try to search api after send invitation

<error>
<status>403</status>
<timestamp>1330485320800</timestamp>
<request-id>VBWC3KKAWB</request-id>
<error-code>0</error-code>
<message>Bad authorization token</message>
</error>

Jeremy Johnstone's picture
Developer Advocate
Joined: 04/17/2011
Tue, 02/28/2012 - 19:53

Hi Julia,

Great! Thanks for taking the time to post back and let us know it's now working for you. :)

-Jeremy