Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

LinkedIn Gem for a Web App

Will Read
Monday, December 7, 2009

There’s an untapped cash cow out there when it comes to recruiting and her name is LinkedIn. Until recently, only LinkedIn had access to your profile and social graph, but all that changed with the release of their OAuth-based API. I’f you’ve hooked into Twitter or Google then this authentication process should feel very familiar to you. To help you along, pengwynn released a LinkedIn gem last week.

What’s lacking is a good controller example, you kind of have to piece it together yourself. So code first, explanation second. Here’s what a simple LinkedIn authentication controller might look like:

<code>
#uncomment the line below if you aren't using bundler
#require 'rubygems'
require 'linkedin'

class AuthController < ApplicationController

  def index
    # get your api keys at https://www.linkedin.com/secure/developer
    client = LinkedIn::Client.new("your_api_key", "your_secret")
    request_token = client.request_token(:oauth_callback =>
                                      "http://#{request.host_with_port}/auth/callback")
    session[:rtoken] = request_token.token
    session[:rsecret] = request_token.secret

    redirect_to client.request_token.authorize_url

  end

  def callback
    client = LinkedIn::Client.new("your_api_key", "your_secret")
    if session[:atoken].nil?
      pin = params[:oauth_verifier]
      atoken, asecret = client.authorize_from_request(session[:rtoken], session[:rsecret], pin)
      session[:atoken] = atoken
      session[:asecret] = asecret
    else
      client.authorize_from_access(session[:atoken], session[:asecret])
    end
    @profile = client.profile
    @connections = client.connections
  end
end
</code>

So the flow your user sees is this:

  • visit /auth/ which automatically redirects me to log in via LinkedIn
  • type in my LinkedIn user name and password, click submit
  • submitting takes me to /auth/callback which might show my profile and connections

What the code does:

  • creates a new LI client based on your credentials as a LinkedIn developer
  • get a request token (pay attention, there’s 2 kinds) , and sets the callback to your callback action
  • saves off the request token-token and the request token-secret into the session, you’ll need to reconstruct the request token in the callback, and the request token itself doesn’t have a marshal-load method defined.
  • sends the user off to the LinkedIn log in page
    — user logs in and is send to the callback action —
  • create a new LI client with the developer key and secret from LinkedIn
  • check to see if the access token (2nd kind of token) has been created before
  • create the access token using the oauth_verifier sent from LinkedIn and the old request token (1st kind) that you save in the session.
  • authorize the client and save off the access token info so you don’t have to send your user back to LI when he comes back (*here I save the access token into the session for simplicity in the example, you should put this in a database probably)
  • if the access token exists, just authorize the client usoing the access token
  • finally, use the client to do interesting things like show the user his profile and his connections.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter

10 Comments

  1. Wynn Netherland says:

    Very nice, Will! Mind if I add that to the docs?

    December 8, 2009 at 12:11 pm

  2. Will Read says:

    Thanks Wynn! Yes, please add anything from here to the docs that you see fit. And thanks for making a great gem!

    December 8, 2009 at 12:18 pm

  3. Vincent RABAH says:

    Oupssss :(

    /var/lib/gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:443:in `load_missing_constant’: uninitialized constant ApplicationController (NameError)
    from /var/lib/gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:80:in `const_missing’
    from /var/lib/gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:92:in `const_missing’
    from ./test2.rb:6

    December 9, 2009 at 2:20 am

  4. Will Read says:

    @Vincent – you may need to require rubygems. I’m using bundler on my project, so I initially omitted it from the code. I’ve since added a comment at the top of the code.

    December 9, 2009 at 9:32 am

  5. Vincent RABAH says:

    I already added it ! And then got this error :
    I’m using ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux] on kubuntu 9.10 64bits .

    Thx

    December 9, 2009 at 11:53 am

  6. Saurabh Bhatia says:

    Hey Will

    Thanks for the article.

    I am getting the following error. On googling it shows that some oauth parameter is getting duplicated. is it the authenticity token, but i think the code already takes care of it, if it is already genereated

    OAuth::Problem in LinkedinController#create
    parameter_absent

    /usr/local/lib/ruby/gems/1.8/gems/oauth-0.3.6/lib/oauth/consumer.rb:167:in `request’
    /usr/local/lib/ruby/gems/1.8/gems/oauth-0.3.6/lib/oauth/consumer.rb:183:in `token_request’
    /usr/local/lib/ruby/gems/1.8/gems/oauth-0.3.6/lib/oauth/tokens/request_token.rb:18:in `get_access_token’
    /usr/local/lib/ruby/gems/1.8/gems/linkedin-0.1.5/lib/linked_in/client.rb:35:in `authorize_from_request’
    /home/saurabh/linkedin/app/controllers/linkedin_controller.rb:25:in `create’

    January 21, 2010 at 3:24 am

  7. cristian says:

    “clearly you won’t want this to be hard coded to localhost:3000″

    You might just use “http://#{request.host_with_port}/auth/callback” instead.

    January 21, 2010 at 4:30 am

  8. cristian says:

    I’m having the same problem as Saurabh Bhatia.
    I’m using oauth 0.3.6 and linkedin 0.1.6.

    Still struggling with it…

    January 21, 2010 at 5:43 am

  9. cristian says:

    I got it fixed now. I had a typo in my code. The params for the call: LinkedIn::Client.new() wre nil.

    January 21, 2010 at 6:59 am

  10. Will Read says:

    I’ll update the blog with your suggestion cristian

    January 21, 2010 at 11:59 am

Add New Comment Cancel reply

Your email address will not be published.

Will Read

Will Read
San Francisco

Recent Posts

  • Org Chart Growth and Keeping Our “Flatness”
  • Releasing When It’s Ugly
  • “Drinking the Kool-Aid™” How We Create Value Alignment
Subscribe to Will's Feed

Author Topics

agile (31)
bloggerdome (3)
process (1)
"soft" ware (16)
feedback (1)
engines (1)
documentation (1)
tdd (2)
bdd (1)
breakfast (1)
pairing (1)
testing (3)
api (2)
bug (1)
chore (1)
velocity (1)
oauth (1)
queues (3)
version control (1)
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >