title: Invalid Signature LinkedIn Oauth while getting access token
body: <p>I am trying dearly to add LinkedIn OAuth to a Phonegap application that I have created to allow users to automatically post to their LinkedIn public profile. I seem to be having trouble retrieving the access token from LinkedIn REST API via the Childbrowser plugin. To sign my REST API calls, I am using the OauthSimple plugin, in javascript.</p>
  
  <p>When I send my signed POST to the REST API, I receive an 401 Unauthorized error. It specifies that I have an invalid signature and I can't figure out for the life of me what is wrong.</p>
  
  <p>This is the json response I receive from LinkedIn when I make the request for the access token:</p>
  
  <pre><code>{"readyState":4,
  "responseText":"oauth_problem=signature_invalid&amp;
  oauth_problem_advice=com.linkedin.security.auth.pub.LoginDeniedInvalidAuthTokenException%20
  while%20obtaining%20request%20token%20for%20%3APOST%26
  https%253A%252F%252Fapi.linkedin.com%252Fuas%252Foauth%252F
  accessToken%26
  oauth_consumer_key%253Dkivazo8r4xr3%2526
  oauth_nonce%253D6ruTZ%2526
  oauth_signature_method%253DHMAC-SHA1%2526
  oauth_timestamp%253D1360525594%2526
  oauth_token%253D0011aab8-0cf0-4555-ba44-304b34e4b636%2526
  oauth_verifier%253D32140%2526
  oauth_version%253D1.0,
  "status":401,
  "statusText":"Unauthorized"}
  </code></pre>
  
  <p>If you would like to have a look at my javascript, here are my functions:</p>
  
  <pre><code>function parametersFromUrl(url) {
      var result = {};
      //Remove everything up to where the parameters start. could be after # or after ?
      url = url.substr(url.indexOf('?') + 1).substr(url.indexOf('#') + 1)
      //Replace html escape characters
      url = url.replace(/%23/g, '#').replace(/%26/g, '&amp;').replace(/%3D/g, '=');
      var parameters = url.split('&amp;');
      for(var i = 0; i &lt; parameters.length; i++) {
          var parameter = parameters[i].split('=');
          result[parameter[0]] = parameter[1];
      }
      return result;
  }
  
  /* -- Linkedin START -- */
  
  var Linkedin = {
      init:function() {
          var signatures = { consumer_key: '555555', shared_secret: '555555' };
          var simple = new OAuthSimple(signatures.consumer_key, signatures.shared_secret);
          Linkedin.getRequestToken(simple, signatures);
      },
      getRequestToken:function(simple, signatures) {
          var result = simple.reset().sign({
              action: 'POST',
              path: 'https://api.linkedin.com/uas/oauth/requestToken',
              signatures: signatures
          });
          console.log(result);
          console.log(result.signed_url);
          jQuery.ajax({
              url: result.signed_url,
              type: 'POST',
              success: function(data) {
                  jQuery.extend(signatures, parametersFromUrl(data));
                  console.log(signatures['oauth_token']);
                  Linkedin.childBrowserAuthenticate(simple, signatures);
              },
              error: function() {
                  console.log('error');
              }
          });
      },
      childBrowserAuthenticate:function(simple, signatures) {
          ChildBrowser.install();
          var childBrowser = window.plugins.childBrowser;
          var browserUrl = simple.reset().sign({
              path: signatures['xoauth_request_auth_url']
          }).signed_url;
          browserUrl = browserUrl + '&amp;oauth_token=' + signatures['oauth_token'];
          childBrowser.showWebPage(decodeURIComponent(browserUrl));
  
          function finish(err) {
              if (err) onFailure(err);
              childBrowser.onClose = null;
              childBrowser.close();
          }
  
          childBrowser.onLocationChange = function(loc) {
              if (loc.indexOf('oauth_problem') &gt; -1) {
                  finish('User authorization error');
              } else if (loc.indexOf('oauth_verifier') &gt; -1) {
                  alert('good');
                  finish();
                  $.each(signatures, function(i,item) {
                      console.log(i);
                      console.log(item);
                  });
                  console.log("next");
                  params = parametersFromUrl(loc);
                  jQuery.extend(signatures, params);
                  $.each(signatures, function(i,item) {
                      console.log(i);
                      console.log(item);
                  });
                  Linkedin.getAccessToken(simple, signatures);
              }
          };
  
          childBrowser.onClose = function() {
              finish('User cancelled authorization.');
          };
      },
      getAccessToken:function(simple, signatures) {
          console.log("last");
          $.each(signatures, function(i,item) {
                      console.log(i);
                      console.log(item);
                  });
  
          var requestUrl = simple.reset().sign({
              action: 'POST',
              path: 'https://api.linkedin.com/uas/oauth/accessToken',
              parameters: {
                  'oauth_verifier': signatures.oauth_verifier,
                  'oauth_token': signatures.oauth_token,
                  'oauth_token_secret': signatures.oauth_token_secret,
                  'oauth_version': "1.0"
              }
          }).signed_url;
          console.log(requestUrl);
          jQuery.ajax({
              url: requestUrl,
              type: 'POST',
              success: function(data) {
                  jQuery.extend(signatures, parametersFromUrl(data));
                  $.each(signatures, function(i,item) {
                      console.log(i);
                      console.log(item);
                  });
                  Linkedin.getUserProfile();
              },
              error: function(resp) {
                  alert('crap');
                  console.log(resp);
              }
          });
      },
      getUserProfile:function() {
          var result = simple.reset().sign({
              action: 'GET',
              path: 'https://api.linkedin.com/v1/people/~:(first-name,last-name,headline,picture-url)',
              parameters: {
                  format: 'json'
              }
          });
  
          jQuery.ajax({
              url: result.signed_url,
              success: function(userData) {
                  onSuccess(userData);
                  alert('success');
                  alert(userData);
              },
              error: function(resp) {
                  onFailure('Failed to get profile information')
              }
          });
      }
  };
  
  /* -- Linkedin END -- */
  </code></pre>
  
  <p>When I make a request (POST) to LinkedIn REST API to get access token, my url looks like this:</p>
  
  <pre><code>https://api.linkedin.com/uas/oauth/accessToken?oauth_consumer_key=555555&amp;oauth_nonce=KXuSN&amp;oauth_signature=rk7eNjTxlhi0UOppOPfA%2BYvQ8uM%3D&amp;oauth_signature_method=HMAC-SHA1&amp;oauth_timestamp=1360527087&amp;oauth_token=206e2377-c790-49a6-839c-a996cadfbdfc&amp;oauth_verifier=62355&amp;oauth_version=1.0
  </code></pre>
  
  <p>I compared my oauth signature to the one generated by the Linkedin oauth console and they arent the same. What could be wrong?</p>
  
  <p>I used <a href="https://clearblade.wordpress.com/2012/08/09/oauth-with-worklight-cordova-childbrowser-plugin/" rel="nofollow">this tutorial</a> to guide me through the process.</p>
  
  <p>If you need any more information, please let me know and I will add to my question.</p>
  
  <p>Thank you so much!</p>