Announcement Announcement Module
Collapse
No announcement yet.
LinkedIn JS API token exchange to REST token using Spring Social for Linkedin Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • LinkedIn JS API token exchange to REST token using Spring Social for Linkedin

    I'm trying to do the following:

    Let the user authenticate and authorize through Linkedin using Linkedin JSAPI, then take the authentication details and send them to my server to get the user profile via server side communication.

    I got the Linkedin button setup, got the authorization cookie all the way to my server (as described here), and was able to verify that the token is indeed signed correctly with my secret key.

    Now I'm stuck at the point where I am supposed to take the token I got from JSAPI and exchange it for an access token.

    This is the code I'm using, as mentioned it uses Spring Social for Linkedin, and it doesn't work as it throws a 401 Unauthorized response:

    LinkedInConnectionFactory connectionFactory =
    new LinkedInConnectionFactory(myLinkedinId, myLinkedinSecret);
    OAuth1Operations oauthOperations = connectionFactory.getOAuthOperations();
    AuthorizedRequestToken art = new AuthorizedRequestToken(new OAuthToken(theTokenIGotFromJSAPI, myLinkedinSecret), howDoICalculateThisSignature);
    OAuthToken accessGrant = oauthOperations.exchangeForAccessToken(art, null);
    if (accessGrant == null) return null;
    Connection<LinkedIn> connection = connectionFactory.createConnection(accessGrant);
    if (connection != null) {
    LinkedIn linkedin = connection.getApi();
    return linkedin.profileOperations().getUserProfile();
    }

    What I'm actually confused about is the AuthorizedRequestToken object. The theTokenIGotFromJSAPI part is simple enough I think, it's just access_token from JSAPI, but what about myLinkedinSecret, is it just my linkedin secret key? what about howDoICalculateThisSignature, how do I create that one? Do I use the same hash method as I used to validate the linkedin response and hash the access_token with my secret linkedin key?

    In the linkedin page, it says:

    You need to pass four values as query parameters:
    1. oauth_consumer_key, to identify yourself
    2. xoauth_oauth2_access_token parameter, set to the value of the access_token field in the cookie.
    3. signature_method set to HMAC-SHA1
    4. signature, calculated as described in the OAuth 1.0a spec
    So (1) is automatically done by the connection I suppose, (2) is the access token I provided, but how do I do (3) and (4)?

    Is there a better way to do this?

    I'm using Spring Social v1.0.2.RELEASE, and social-Linkedin v1.0.0.RC1
    I can upgrade or change versions as needed.

  • #2
    Honestly, I've never tried using a token obtained through the JSAPI, but I am intrigued by what you're doing and hope to be able to help you solve the problem. But because I haven't done this thing before, I'm only guessing until I have a chance to try it for myself.

    A number of things caught my eye as I read this and I'm fairly certain that this can't (at least not easily) be done with Spring Social.

    The code you show in your post shows the process of exchanging an OAuth 1.0a request token for an OAuth 1.0a access token. But the LinkedIn documentation shows how to exchange an OAuth 2 access token (bearer token) for an OAuth 1.0 access token. Those are two different things and involves a slightly different process.

    In OAuth 1.0a, you'd exchange a request token for an access token via the https://api.linkedin.com/uas/oauth/accessToken endpoint. That's the same endpoint you would exchange an OAuth 2 bearer token for an OAuth 1.0a access token. But the parameters are different.

    When you call oauthOperations.exchangeForAccessToken(), it goes through the process described at https://developer.linkedin.com/docum...ng-oauth-token under the heading "Request the Access Token". But what you're needing is for it to POST to that endpoint with an xoauth_oauth2_access_token set to the OAuth 2 bearer token you got from the JSAPI. As it stands now, Spring Social doesn't support that exchange. You may request it by submitting an improvement issue at https://jira.springsource.org/browse/SOCIALLI...but read on to understand why I may not fulfill that request.

    Even then, here's the catch: Those instructions tell how to exchange an OAuth 2 bearer token for an OAuth 1.0a access token. In the latest Spring Social snapshot build, Spring Social LinkedIn has been fully converted to use OAuth 2. Therefore, exchanging an OAuth 2 access token for an OAuth 1.0a access token will do you no good.

    My guess is that you can use the OAuth 2 bearer token as-is with the newest Spring Social LinkedIn (haven't tried it, but I'd wager that it works). But then there's another catch: The bearer token that the JSAPI gives you is was obtained via an implicit grant and will expire after ~30 minutes. Therefore, even if they work, they'll only work for 30 minutes. So, what you really need is a way to exchange that temporary token for one that lives longer and that comes with a refresh token. I'm not sure if LinkedIn offers that kind of exchange or not.

    In short, what you're trying to do won't work, what will work won't do you any good with the latest Spring Social builds, and what should work may or may not be possible with LinkedIn. More research is certainly in order. I'll dig around...let me know if you find anything that might help us get a long-lived OAuth 2 bearer token from a JSAPI-issued token.

    Comment


    • #3
      First of all, thanks for your quick response, I've been struggling with this implementation for three days already, after having completed the Facebook integration much faster (same process, but somehow easier to do with Facebook).

      If I understand the statement in this linkedin tutorial correctly, the token received from Linkedin does not expire after 30 minutes.
      From that tutorial:

      Congratulations! You have successfully exchanged your JS API token for a REST API token. You can now make any of our REST API calls from your backend environment. The lifetime of this new token will match whatever the user has specified (normally this is infinite), so you can make background calls whenever you want - you are no longer bound by the short lifetime of the bearer tokens


      The thing is, Facebook supports this process well (so does Spring's facebook implementation), and linkedin is obviously trying to do the same, so I think it should be solvable for someone with the right knowledge. I have to admit that I'm too much of a noob to do this within a reasonable timeframe, so if you find the time to help I'd be much obliged.

      I have open-sourced the project my startup is based on, so anything I learn in the process will also benefit the community.

      Comment


      • #4
        To be clear, there are at least 3 kinds of tokens that you can get from LinkedIn:
        - An OAuth 1.0a access token, obtained either through a standard OAuth 1.0a "dance" or by exchanging a client-side bearer token for an OAuth 1.0a access token. This token does not expire.
        - An OAuth 2 client-side bearer token, obtains through JSAPI. This token will expire after ~30 minutes (per that same tutorial).
        - An OAuth 2 bearer token, obtained through a standard OAuth 2 "dance". This token likely expires, but even if it does, it can be renewed with a refresh token.

        That tutorial talks about exchanging the expiring client-side bearer token for a non-expiring OAuth 1.0a access token. This is a non-standard (LinkedIn-only, as far as I know) exchange. Could I implement this exchange in Spring Social? Sure. But it wouldn't do any good because the latest Spring Social LinkedIn builds use an OAuth 2 bearer token. Obtaining an OAuth 1.0a access token will do no good.

        Now, what *would* be useful is a way to exchange the short-lived OAuth 2 bearer token obtained from JSAPI for a longer-lived (and refreshable) OAuth 2 bearer token. Is that possible? I don't know. I've not seen anything in the LinkedIn docs about it, but it might be there and I've overlooked it. If it is possible, then I would certainly entertain the idea of implementing it in Spring Social.

        Comment


        • #5
          It is better to have the REST token for using the spring social for Linkedin. I am glad to become a part of this forums where I could get access to all these amazing technologies.

          Comment


          • #6
            I was very interested to read this thread. We use spring-social and spring-social-linkedin in our applications and we have recently upgraded to the OAuth2 integration. As I think has surfaced in other threads, both the OAuth1 and OAuth2 tokens do in fact expire and cannot be refreshed. One can only get a new token via the OAuth dance or the JSAPI.

            So, wishing to maintain our LinkedIn authorizations with the least inconvenience to the end user, I have found myself tasked with:

            * adding code to exchange the JSAPI token for an OAuth1 token and save it in the connection repository
            * writing derivatives of the spring-social-linkedin classes to support use of the REST API with both OAuth1 and OAuth2 connections

            If anyone finds a way to exchange the JSAPI token for an OAuth2 token, that would be great. Otherwise, if anything I'm doing can be of use upstream, I'd be happy to share more details.

            Comment

            Working...
            X