Class: OmniAuth::Strategies::LinkedIn

Inherits:
Object
  • Object
show all
Includes:
OmniAuth::Strategy
Defined in:
lib/omniauth/strategies/linkedin.rb

Overview

Authentication strategy for connecting by [exchanging LinkedIn JSAPI for REST API OAuth Tokens](developer.linkedin.com/documents/exchange-jsapi-tokens-rest-api-oauth-tokens).

Defined Under Namespace

Classes: InvalidSecureCookieError, LinkedinServerError, NoSecureCookieError

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#access_tokenObject

Returns the value of attribute access_token.



83
84
85
# File 'lib/omniauth/strategies/linkedin.rb', line 83

def access_token
  @access_token
end

Instance Method Details

#callback_phaseObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/omniauth/strategies/linkedin.rb', line 97

def callback_phase 
  if request_contains_secure_cookie?
    # We should already have an oauth2 token from secure cookie. 
    # Need to exchange it for an oauth token for REST API
    self.access_token = client.get_access_token(nil, {}, {:xoauth_oauth2_access_token => secure_cookie['access_token']})
    super
  else
    raise NoSecureCookieError, 'must pass a `linkedin_oauth_XXX` cookie'
  end
rescue NoSecureCookieError => e
  fail!(:invalid_credentials, e)
rescue InvalidSecureCookieError => e
  fail!(:invalid_credentials, e)
rescue LinkedinServerError => e
  fail!(:invalid_response, e)
rescue ::Timeout::Error => e
  fail!(:timeout, e)
rescue ::Net::HTTPFatalError, ::OpenSSL::SSL::SSLError => e
  fail!(:service_unavailable, e)
rescue ::OAuth::Unauthorized => e
  fail!(:invalid_credentials, e)
rescue ::MultiJson::DecodeError => e
  fail!(:invalid_response, e)
rescue ::OmniAuth::NoSessionError => e
  fail!(:session_expired, e)
end

#clientObject



124
125
126
# File 'lib/omniauth/strategies/linkedin.rb', line 124

def client
  @client ||= OAuth::Consumer.new(options.api_key, options.secret_key, options.client_options)
end


140
141
142
143
144
145
146
147
# File 'lib/omniauth/strategies/linkedin.rb', line 140

def parse_secure_cookie(cookie)
  payload = MultiJson.decode cookie
  if validate_signature(payload)
    payload
  else
    raise InvalidSecureCookieError, 'secure cookie signature validation fails'
  end
end

#raw_infoObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/omniauth/strategies/linkedin.rb', line 63

def raw_info
  @raw_info ||= lambda do
    # Add retry logic to user info fetching because sometimes Linkedin gets back with the following data:
    # raw_info: {
    #   errorCode: 0,
    #   message: "Could not find person based on: ~",
    #   requestId: "***************",
    #   status: 404,
    #   timestamp: 1393490622830.0
    # }
    try_count = 0
    begin
      raw_info = MultiJson.decode(access_token.get("/v1/people/~:(#{options.fields.join(',')})?format=json").body)
      try_count += 1
    end while raw_info['errorCode'].present? and try_count < 5
    raise LinkedinServerError, raw_info['message'] if raw_info['errorCode'].present?
    raw_info
  end.call
end


136
137
138
# File 'lib/omniauth/strategies/linkedin.rb', line 136

def raw_secure_cookie
  request.cookies["linkedin_oauth_#{options.api_key}"]
end

#request_contains_secure_cookie?Boolean

Returns:

  • (Boolean)


128
129
130
# File 'lib/omniauth/strategies/linkedin.rb', line 128

def request_contains_secure_cookie?
  secure_cookie && secure_cookie['access_token']
end

#request_phaseObject



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/omniauth/strategies/linkedin.rb', line 85

def request_phase
  url = callback_url
  url << "?" unless url.match(/\?/)
  url << "&" unless url.match(/[\&\?]$/)
  url << Rack::Utils.build_query(request.params)
  redirect url
rescue ::Timeout::Error => e
  fail!(:timeout, e)
rescue ::Net::HTTPFatalError, ::OpenSSL::SSL::SSLError => e
  fail!(:service_unavailable, e)
end


132
133
134
# File 'lib/omniauth/strategies/linkedin.rb', line 132

def secure_cookie
  @secure_cookie ||= raw_secure_cookie && parse_secure_cookie(raw_secure_cookie)
end

#user_nameObject



165
166
167
168
# File 'lib/omniauth/strategies/linkedin.rb', line 165

def user_name
  name = "#{raw_info['firstName']} #{raw_info['lastName']}".strip
  name.empty? ? nil : name
end

#validate_signature(payload) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/omniauth/strategies/linkedin.rb', line 149

def validate_signature(payload)
  valid = false
  if payload['signature_version'] == '1' or payload['signature_version'] == 1
    if !payload['signature_order'].nil? and payload['signature_order'].is_a?(Array)
      plain_msg = payload['signature_order'].map {|key| payload[key]}.join('')
      if payload['signature_method'] == 'HMAC-SHA1'
        signature = Base64.encode64(OpenSSL::HMAC.digest('sha1', options.secret_key, plain_msg)).chomp
        if signature == payload['signature']
          valid = true
        end
      end
    end
  end
  valid
end