Subscribe now to Datacamp and save 63% - Subscribe now
Authenticate using OAuth 2.0 and the LinkedIn API
Share this post

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


Subscribe to my Newsletter


  1. Get Your OAuth Credentials
  2. Authenticate Using OAuth 2.0
  3. Get Your Own User Information
  4. Simple Steps to Find Any Company ID on LinkedIn
  5. How to Post On LinkedIn API With Python

Import Libraries

To run the OAuth 2.0 authentication you will need to install and import all those libraries.

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.

You Might Also Like  Random User-Agent With Python and BeautifulSoup (by JR Oakes)

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.

You Might Also Like  Backup Google Search Console Data Into MySQL With Python

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.