bannerColor WARNING_YELLOW templateName stackForums

Common Issues with OAuth Authentication

Here are some tips to keep in mind while debugging problems related to OAuth authentication. We'll often include an "oauth_problem" HTTP header with further description of an issue with validating your OAuth signatures.

Adding Query Parameters

When your GET queries work fine until you add query parameters - and then you get 401 responses after adding the query parameters, the problem is almost certainly that you're trying to add the query parameters as part of the URL. You need to add the query parameters to the OAuth request object in whatever way the OAuth library you're using expects them. There's usually a way to set the URL and separately pass in the query parameters - this is required so that OAuth will generate the signature correctly. If you're unsure how to do this with your library, take a look at our Libraries and Tools page for examples of how the LinkedIn libraries do this piece.

Multiple Parameters of the Same Name

For some requests, you can send multiple values together (for instance, with share you can send "type=SHAR&type=CMPY"). Some OAuth libraries don't sign these requests properly, so you get a 401 response (incorrect signature) when using these libraries in these cases. To test whether this is the issue, check the request in our OAuth Test Console or try the call with only one of these parameters to see if it succeeds.

Sending an Authorization header

For GET requests, our servers will accept OAuth parameters sent as query parameters in the URL string, but for POST requests, you must use the Authorization header as detailed in the OAuth Specification. Note that using the header is the "right way" to use OAuth authentication and you should use it whenever possible, since it will work correctly for both GET and POST requests.

Most OAuth libraries will create this header for you, and as with all things you're encouraged to leverage an existing OAuth library for signing and making your calls, but for a quick overview, an HTTP header might look like this (on a single line, separated by ", ":

Authorization: OAuth oauth_nonce="oqwgSYFUD87MHmJJDv7bQqOF2EPnVus7Wkqj5duNByU", 
oauth_signature_method="HMAC-SHA1", 
oauth_timestamp="1259178158", 
oauth_consumer_key="ABCDEFGHIJKLMNOPQRSTUVWXYZ", 
oauth_signature="TLQXuUzM7omwDbtXimn6bLDvfF8%3D", 
oauth_version="1.0"

Please note that the HTTP header is a single header -- not an HTTP header for each component.

Properly handling oauth_token_secret

Twitter is particularly lenient with the use of oauth_token_secret when validating requests on the accessToken and resource authorization steps. Because of this leniency, many OAuth libraries written with Twitter in mind don't handle the oauth_token_secret steps properly. LinkedIn will return to you an oauth_token_secret in both the requestToken and accessToken responses.

In the case of the requestToken step, you must use the oauth_token_secret returned in conjunction with your oauth_consumer_secret when generating your signature for the authorization and accessToken steps.

After successfully stepping through the requestToken, authorization, you're successful request for an accessToken will return to you a new oauth_token_secret, which you then use in subsequent resource requests (for profiles, network updates, etc.)

When using an oauth_token_secret in conjunction with your oauth_consumer_secret, the amalgamation will look something like this:

url_escape( url_escape(oauth_consumer_secret) + "&" + url_escape(oauth_token_secret) )

For further information on using oauth_token_secret in your requests, consult section 9.4.1 of the OAuth Specification.

Passing oauth_callback in OAuth 1.0a-appropriate steps

In OAuth 1.0a, the oauth_callback parameter is only to be supplied to the requestToken step. Many 1.0-compliant libraries will also pass oauth_callback on the authorization or accessToken steps, both of which will result in an error with LinkedIn. The only appropriate call for an oauth_callback to be specified is requestToken.

Proper handling of XML-based POST & PUT bodies

Many libraries make assumptions about the content disposition of content bodies in POST and PUT requests that do not comply with the OAuth specification.

With LinkedIn's API, you'll always be POSTing or PUTing XML content bodies, which means you need to set your Content-Type header to "text/xml" and insure that the POST body is not calculated as part of the signature. In all versions of OAuth, only POST bodies containing URL-encoded parameters are calculated as part of the signature.

Out of sync timestamps

Your servers making requests must be within 5 minutes of our system clock. Timestamps in OAuth are always represented in epoch time in seconds. In any error response LinkedIn sends you, the current timestamp on our servers is included in an XML body of the response. However, at this time the timestamp we send you is in milliseconds, not seconds. It's quite easy to do the math to convert milliseconds to seconds.

Inclusion of oauth_token as a parameter for signing when unused

There are some interpretations of a vague portion of the OAuth spec that suggest even parameters without values should be included in a signing base string. While this is true, it is predicated on the existence of the parameter and it having no value — not in the case where the parameter wasn't specified at all. Some OAuth libraries (particularly recent versions of SignPost) interpret this part of the spec to include parameters that aren't used in some steps like oauth_token in the requestToken step. At this time, LinkedIn does not support these kind of phantom parameters when calculating signature.

This presentation on SlideShare may also help you in debugging.