The OAuth 2.0 Protocol is a third party protocol used for authentication and authorization. In this article, we will see how to authenticate the LinkedIn API using OAuth 2.0 and Python.
If you haven’t already, make sure that you read how to get LinkedIn API OAuth credentials before starting this tutorial.
This post is part of the complete guide on how to use the LinkedIn API with Python
- Get Your OAuth Credentials
- Authenticate Using OAuth 2.0
- Get Your Own User Information
- Simple Steps to Find Any Company ID on LinkedIn
- How to Post On LinkedIn API With Python
- How to Scrape LinkedIn Jobs with Python
Import Libraries
To run the OAuth 2.0 authentication you will need to install and import all those libraries: requests, random, string and json.
import json
import random
import requests
import string
Read Credentials
Now, let’s create a function that will read the credentials.json
file that we have created in
def read_creds(filename):
'''
Store API credentials in a safe place.
If you use Git, make sure to add the file to .gitignore
'''
with open(filename) as f:
credentials = json.load(f)
return credentials
creds = read_creds('credentials.json')
client_id, client_secret = creds['client_id'], creds['client_secret']
redirect_uri = creds['redirect_uri']
Authorize The API
To authorize the API, you will need to generate a CSRF token to prevent cross-site request forgery. The create_CSRF_token()
function does this.
It creates a random string of letters to use as the CSRF Token.
def create_CSRF_token():
'''
This function generates a random string of letters.
It is not required by the Linkedin API to use a CSRF token.
However, it is recommended to protect against cross-site request forgery
'''
letters = string.ascii_lowercase
token = ''.join(random.choice(letters) for i in range(20))
return token
Then, the authorize()
function says what it does. It will open the authentication URL. Once authorized, it’ll redirect to the redirect URI given.
api_url = 'https://www.linkedin.com/oauth/v2'
def authorize(api_url,client_id,client_secret,redirect_uri):
'''
Make a HTTP request to the authorization URL.
It will open the authentication URL.
Once authorized, it'll redirect to the redirect URI given.
The page will look like an error. but it is not.
You'll need to copy the redirected URL.
'''
# Request authentication URL
csrf_token = create_CSRF_token()
params = {
'response_type': 'code',
'client_id': client_id,
'redirect_uri': redirect_uri,
'state': csrf_token,
'scope': 'r_liteprofile,r_emailaddress,w_member_social'
}
response = requests.get(f'{api_url}/authorization',params=params)
print(f'''
The Browser will open to ask you to authorize the credentials.\n
Since we have not set up a server, you will get the error:\n
This site can’t be reached. localhost refused to connect.\n
This is normal.\n
You need to copy the URL where you are being redirected to.\n
''')
open_url(response.url)
# Get the authorization verifier code from the callback url
redirect_response = input('Paste the full redirect URL here:')
auth_code = parse_redirect_uri(redirect_response)
return auth_code
Get the Access Token
The authorize()
function contains two functions that we need to define: open_url()
and parse_redirect_uri()
.
The former opens the login URL in the browser.
def open_url(url):
'''
Function to Open URL.
Used to open the authorization link
'''
import webbrowser
print(url)
webbrowser.open(url)
The latter checks the redirect uri and extract the access token from it.
def parse_redirect_uri(redirect_response):
'''
Parse redirect response into components.
Extract the authorized token from the redirect uri.
'''
from urllib.parse import urlparse, parse_qs
url = urlparse(redirect_response)
url = parse_qs(url.query)
return url['code'][0]
A third function will be needed to save the access token to your credentials.json
file.
The save_token()
function will make sure that you don’t need to log-in each time.
def save_token(filename,data):
'''
Write token to credentials file.
'''
data = json.dumps(data, indent = 4)
with open(filename, 'w') as f:
f.write(data)
A last function will not be used here, but later when we query the LinkedIn API.
The headers()
function creates the header that will be use in the request made to the API.
def headers(access_token):
'''
Make the headers to attach to the API call.
'''
headers = {
'Authorization': f'Bearer {access_token}',
'cache-control': 'no-cache',
'X-Restli-Protocol-Version': '2.0.0'
}
return headers
Combine All Functions
Now that we have all necessary functions, let’s make a function to run the entire script.
The logic behind the auth()
function goes like this:
- Run the Authentication.
- The first time the function runs, the browser opens asking you to authenticate.
- You will have to manually paste the redirect URI in the prompt.
- The URL will be parsed to extract the access token.
- It will save the access token
- Next time, it will use the access token instead of asking you to authenticate.
def auth(credentials):
'''
Run the Authentication.
If the access token exists, it will use it to skip browser auth.
If not, it will open the browser for you to authenticate.
You will have to manually paste the redirect URI in the prompt.
'''
creds = read_creds(credentials)
print(creds)
client_id, client_secret = creds['client_id'], creds['client_secret']
redirect_uri = creds['redirect_uri']
api_url = 'https://www.linkedin.com/oauth/v2'
if 'access_token' not in creds.keys():
args = client_id,client_secret,redirect_uri
auth_code = authorize(api_url,*args)
access_token = refresh_token(auth_code,*args)
creds.update({'access_token':access_token})
save_token(credentials,creds)
else:
access_token = creds['access_token']
return access_token
Run the Function
To run the function, call the auth()
function using the path to your credentials.json
file.
if __name__ == '__main__':
credentials = 'credentials.json'
access_token = auth(credentials)
The if name equals main line checks whether you are running the module or importing it. If you are importing it, auth()
will not run.
I run the ln_oauth.py
script that I just created using command-line.
$ python ln_oauth.py
Here is what happens.
1. Browser opens asking me to login Linkedin
2. Asks me to Allow the App
3. I am Redirected to a Page that Can’t be Reached
This is normal because I don’t run this on a server. Just copy the localhost:8080/?code...
url.
4. Copy the URL in your Script
The access token is found right after the ?code=
parameter and before the &state
parameter.
You could add the access token straight into your credentials.json
file, or copy it in the prompt of your terminal.
5. The Access Token is then Saved
This is it, in the next post, we are going to see how to use the LinkedIn API using that access token.
Full Code
#!/usr/bin/env python
'''
Simple Authentication script to log-on the Linkedin API
@author: Jean-Christophe Chouinard.
@role: Sr. SEO Specialist at SEEK.com.au
@website: jcchouinard.com
@LinkedIn: linkedin.com/in/jeanchristophechouinard/
@Twitter: twitter.com/@ChouinardJC
'''
import json
import random
import requests
import string
def auth(credentials):
'''
Run the Authentication.
If the access token exists, it will use it to skip browser auth.
If not, it will open the browser for you to authenticate.
You will have to manually paste the redirect URI in the prompt.
'''
creds = read_creds(credentials)
print(creds)
client_id, client_secret = creds['client_id'], creds['client_secret']
redirect_uri = creds['redirect_uri']
api_url = 'https://www.linkedin.com/oauth/v2'
if 'access_token' not in creds.keys():
args = client_id,client_secret,redirect_uri
auth_code = authorize(api_url,*args)
access_token = refresh_token(auth_code,*args)
creds.update({'access_token':access_token})
save_token(credentials,creds)
else:
access_token = creds['access_token']
return access_token
def headers(access_token):
'''
Make the headers to attach to the API call.
'''
headers = {
'Authorization': f'Bearer {access_token}',
'cache-control': 'no-cache',
'X-Restli-Protocol-Version': '2.0.0'
}
return headers
def read_creds(filename):
'''
Store API credentials in a safe place.
If you use Git, make sure to add the file to .gitignore
'''
with open(filename) as f:
credentials = json.load(f)
return credentials
def save_token(filename,data):
'''
Write token to credentials file.
'''
data = json.dumps(data, indent = 4)
with open(filename, 'w') as f:
f.write(data)
def create_CSRF_token():
'''
This function generate a random string of letters.
It is not required by the Linkedin API to use a CSRF token.
However, it is recommended to protect against cross-site request forgery
For more info on CSRF https://en.wikipedia.org/wiki/Cross-site_request_forgery
'''
letters = string.ascii_lowercase
token = ''.join(random.choice(letters) for i in range(20))
return token
def open_url(url):
'''
Function to Open URL.
Used to open the authorization link
'''
import webbrowser
print(url)
webbrowser.open(url)
def parse_redirect_uri(redirect_response):
'''
Parse redirect response into components.
Extract the authorized token from the redirect uri.
'''
from urllib.parse import urlparse, parse_qs
url = urlparse(redirect_response)
url = parse_qs(url.query)
return url['code'][0]
def authorize(api_url,client_id,client_secret,redirect_uri):
# Request authentication URL
csrf_token = create_CSRF_token()
params = {
'response_type': 'code',
'client_id': client_id,
'redirect_uri': redirect_uri,
'state': csrf_token,
'scope': 'r_liteprofile,r_emailaddress,w_member_social'
}
response = requests.get(f'{api_url}/authorization',params=params)
print(f'''
The Browser will open to ask you to authorize the credentials.\n
Since we have not setted up a server, you will get the error:\n
This site can’t be reached. localhost refused to connect.\n
This is normal.\n
You need to copy the URL where you are being redirected to.\n
''')
open_url(response.url)
# Get the authorization verifier code from the callback url
redirect_response = input('Paste the full redirect URL here:')
auth_code = parse_redirect_uri(redirect_response)
return auth_code
def refresh_token(auth_code,client_id,client_secret,redirect_uri):
'''
Exchange a Refresh Token for a New Access Token.
'''
access_token_url = 'https://www.linkedin.com/oauth/v2/accessToken'
data = {
'grant_type': 'authorization_code',
'code': auth_code,
'redirect_uri': redirect_uri,
'client_id': client_id,
'client_secret': client_secret
}
response = requests.post(access_token_url, data=data, timeout=30)
response = response.json()
print(response)
access_token = response['access_token']
return access_token
if __name__ == '__main__':
credentials = 'credentials.json'
access_token = auth(credentials)
This is it, in the next post, we are going to see how to make your first API call using the LinkedIn API.
SEO Strategist at Tripadvisor, ex- Seek (Melbourne, Australia). Specialized in technical SEO. Writer in Python, Information Retrieval, SEO and machine learning. Guest author at SearchEngineJournal, SearchEngineLand and OnCrawl.