Skip to content

Instantly share code, notes, and snippets.

@lebedov
Last active February 13, 2019 02:46
Show Gist options
  • Save lebedov/8c3f33ebb55a67b732c1 to your computer and use it in GitHub Desktop.
Save lebedov/8c3f33ebb55a67b732c1 to your computer and use it in GitHub Desktop.
Get LinkedIn access tokens without having to open a web browser.
#!/usr/bin/env python
"""
Get LinkedIn OAuth1 access tokens without having to open a web browser.
Notes
-----
Based upon https://developer.linkedin.com/documents/getting-oauth-token-python
Assumes that the application API key, secret key, user name, and password are stored
in an a configuration file formatted as follows:
[Secrets]
API_KEY = WWWWWWWW
SECRET_KEY = XXXXXXXX
NAME = YYYYYYYY
PASSWORD = ZZZZZZZZ
"""
import re
import ConfigParser as cp
import oauth2
import urlparse
import lxml.html
import mechanize
# Read secrets:
cfg_file = 'linkedin_config'
config = cp.ConfigParser()
config.read(cfg_file)
if not config.has_section('Secrets'):
raise RuntimeError('no secrets specified')
secrets = {}
for s in config.items('Secrets'):
secrets[s[0]] = s[1]
# Set up headless browser:
br = mechanize.Browser()
br.set_cookiejar(mechanize.CookieJar())
br.set_handle_redirect(True)
br.set_handle_robots(False)
# Get request token:
consumer = oauth2.Consumer(secrets['api_key'], secrets['secret_key'])
client = oauth2.Client(consumer)
request_token_url = 'https://api.linkedin.com/uas/oauth/requestToken'
response, content = client.request(request_token_url, 'POST')
if response['status'] != '200':
raise Exception('Invalid response')
request_token = dict(urlparse.parse_qsl(content))
print 'request token: ', request_token['oauth_token']
print 'request token secret: ', request_token['oauth_token_secret']
# Use token to redirect to user login:
authorize_url = 'https://api.linkedin.com/uas/oauth/authorize'
redirect_url = '%s?oauth_token=%s' % (authorize_url, request_token['oauth_token'])
# Login with mechanize:
br.open(redirect_url)
br.select_form(nr=0)
br.form['session_key'] = secrets['username']
br.form['session_password'] = secrets['password']
br.submit()
html = br.response().read()
tree = lxml.html.fromstring(html)
oauth_verifier = tree.xpath('.//div[@class="access-code"]')[0].text_content()
# Use PIN to obtain access token:
token = oauth2.Token(request_token['oauth_token'],
request_token['oauth_token_secret'])
token.set_verifier(oauth_verifier)
access_token_url = 'https://api.linkedin.com/uas/oauth/accessToken'
client = oauth2.Client(consumer, token)
response, content = client.request(access_token_url, 'POST')
access_token = dict(urlparse.parse_qsl(content))
print 'access token: ', access_token['oauth_token']
print 'access token secret: ', access_token['oauth_token_secret']
#!/usr/bin/env python
"""
Get LinkedIn OAuth2 access tokens without having to open a web browser.
Notes
-----
Requires `python-linkedin <https://github.com/ozgur/python-linkedin>`_.
Assumes that the application API key and secret key are stored in a
configuration file formatted as follows:
[Secrets]
API_KEY = WWWWWWWW
SECRET_KEY = XXXXXXXX
"""
import re
import ConfigParser as cp
import urlparse
from linkedin import linkedin
import mechanize
from mechanize import _response
from mechanize import _rfc3986
# Read secrets:
cfg_file = 'linkedin_config'
config = cp.ConfigParser()
config.read(cfg_file)
if not config.has_section('Secrets'):
raise RuntimeError('no secrets specified')
secrets = {}
for s in config.items('Secrets'):
secrets[s[0]] = s[1]
class MyRedirectHandler(mechanize.HTTPRedirectHandler):
def http_error_302(self, req, fp, code, msg, headers):
# Code from mechanize._urllib2_fork.HTTPRedirectHandler:
if 'location' in headers:
newurl = headers.getheaders('location')[0]
elif 'uri' in headers:
newurl = headers.getheaders('uri')[0]
else:
return
newurl = _rfc3986.clean_url(newurl, "latin-1")
newurl = _rfc3986.urljoin(req.get_full_url(), newurl)
new = self.redirect_request(req, fp, code, msg, headers, newurl)
if new is None:
return
if hasattr(req, 'redirect_dict'):
visited = new.redirect_dict = req.redirect_dict
if (visited.get(newurl, 0) >= self.max_repeats or
len(visited) >= self.max_redirections):
raise HTTPError(req.get_full_url(), code,
self.inf_msg + msg, headers, fp)
else:
visited = new.redirect_dict = req.redirect_dict = {}
visited[newurl] = visited.get(newurl, 0) + 1
fp.read()
fp.close()
# If the redirected URL doesn't match
new_url = new.get_full_url()
if not re.search('^http(?:s)?\:\/\/.*www\.linkedin\.com', new_url):
return _response.make_response('', headers.items(), new_url, 200, 'OK')
else:
return self.parent.open(new)
http_error_301 = http_error_303 = http_error_307 = http_error_302
http_error_refresh = http_error_302
# Set up headless browser:
br = mechanize.Browser()
br.set_cookiejar(mechanize.CookieJar())
br.handler_classes['_redirect'] = MyRedirectHandler
br.set_handle_redirect(True)
br.set_handle_robots(False)
return_uri = 'http://localhost:9000'
auth = linkedin.LinkedInAuthentication(secrets['api_key'],
secrets['secret_key'],
return_uri,
linkedin.PERMISSIONS.enums.values())
br.open(auth.authorization_url)
br.select_form(nr=0)
br.form['session_key'] = secrets['username']
br.form['session_password'] = secrets['password']
r = br.submit()
auth.authorization_code = urlparse.parse_qs(urlparse.urlsplit(r.geturl()).query)['code']
access_token = auth.get_access_token()
app = linkedin.LinkedInApplication(token=access_token)
@shanto12
Copy link

Can you write this in python 3 with requests library please

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment