Login with LinkedIn using PHP

LinkedIn is one of the most popular social networks with a huge user base. Like the Facebook, Twitter and Google authentication, LinkedIn also used for the user authentication in the web application. If you want to allow the user to login with the social account in the website, LinkedIn login option can provide additional value to social login system. Sign In with LinkedIn feature allows the user to log into the web application using their LinkedIn account without creating a new account.

LinkedIn API helps to authenticate and access user’s account information in the web application. You can easily integrate LinkedIn Authentication using PHP OAuth library. OAuth library allows you to connect LinkedIn API and implement Login with LinkedIn account using PHP. In this tutorial, we will show you how to integrate user registration and login system with LinkedIn using PHP and store the LinkedIn account data in the MySQL database. Our example LinkedIn login script uses PHP OAuth 2.0 and LinkedIn login API v2 to build LinkedIn login system with PHP and MySQL.

Before you begin to integrate Sign In with LinkedIn using PHP, take a look at the file structure.

linkedin_login_with_php/
├── config.php
├── index.php
├── logout.php
├── User.class.php
├── linkedin-oauth-client-php/
├── images/
│   ├── linkedin-sign-in-btn.png
└── css/
    └── style.css

Create LinkedIn App

To access LinkedIn API you need to create an App in the LinkedIn Developer panel. Client ID and Client Secret are required to specify at the time of calling the LinkedIn API. Follow the step-by-step guide to create a new LinkedIn App and generate Client ID and Client Secret in the LinkedIn Developers panel.

  • Visit LinkedIn Developers page and login with your LinkedIn account credentials.
  • Click the Create app button to create a new LinkedIn app.
  • Provide the information about your app and click Create app to submit the app registration form.
    • App name – Name of the application.
    • Company – Name of your company.
    • App description – Workflow of the application.
    • App logo – Logo to display on the OAuth dialog.
    • Privacy policy URL – URL of the Privacy Policy page.
    • Business email – Your email address.
    • Products – Select the products that you’d like to add to your app.
  • On successful app creation, the page will be redirected to the App settings screen.
  • Switch to the Auth tab » Scroll down to OAuth 2.0 settings section.
    • Specify the redirect URL in the Redirect URLs fields and Update the App settings.
    linkedin-php-oauth-create-app-redirect-url-settings-codexworld

    Note that: The Redirect URLs must be matched with the Redirect URL that specified in the script.

  • In the Application credentials section, you will see the Client ID and Client Secret of your LinkedIn App. The App ID and App secret need to be specified in the script at the time of the LinkedIn API call.
    linkedin-php-oauth-api-create-app-client-id-secret-codexworld

Create Database Table

To store the user’s profile information from LinkedIn, a table needs to be created in the database. The following SQL creates an users table with some basic fields in the MySQL database to hold the LinkedIn account information.

CREATE TABLE `users` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `oauth_provider` enum('linkedin','google','facebook','twitter') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'linkedin',
 `oauth_uid` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 `first_name` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
 `last_name` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
 `email` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `gender` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
 `locale` varchar(25) COLLATE utf8_unicode_ci DEFAULT NULL,
 `picture` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL,
 `link` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
 `created` datetime NOT NULL,
 `modified` datetime NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

LinkedIn OAuth Library for PHP

The linkedin-oauth-client-php/ directory contains the OAuth 2.0 PHP client library for LinkedIn API v2. You don’t need to download it separately, all the required files of LinkedIn PHP OAuth are included in our LinkedIn Login PHP source code.

User Class (User.class.php)

The User class handles the database related operations (connect, insert, and update) using PHP and MySQL. It helps to connect to the database and insert/update LinkedIn account data in the users table.

  • __construct() – Connects to the MySQL database.
  • checkUser() – Insert or update the user profile data based on the OAuth provider and ID. Returns the user’s account data as an array.
<?php
/*
 * User Class
 * This class is used for database related (connect, insert, and update) operations
 * @author    CodexWorld.com
 * @url        http://www.codexworld.com
 * @license    http://www.codexworld.com/license
 */
class User {
    private $dbHost     DB_HOST;
    private $dbUsername DB_USERNAME;
    private $dbPassword DB_PASSWORD;
    private $dbName     DB_NAME;
    private $userTbl    DB_USER_TBL;
    
    function __construct(){
        if(!isset($this->db)){
            // Connect to the database
            $conn = new mysqli($this->dbHost$this->dbUsername$this->dbPassword$this->dbName);
            if($conn->connect_error){
                die("Failed to connect with MySQL: " $conn->connect_error);
            }else{
                $this->db $conn;
            }
        }
    }
    
    function checkUser($userData = array()){
        if(!empty($userData)){
            // Check whether user data already exists in database
            $prevQuery "SELECT * FROM ".$this->userTbl." WHERE oauth_provider = '".$userData['oauth_provider']."' AND oauth_uid = '".$userData['oauth_uid']."'";
            $prevResult $this->db->query($prevQuery);
            if($prevResult->num_rows 0){
                // Update user data if already exists
                $query "UPDATE ".$this->userTbl." SET first_name = '".$userData['first_name']."', last_name = '".$userData['last_name']."', email = '".$userData['email']."', locale = '".$userData['locale']."', picture = '".$userData['picture']."', link = '".$userData['link']."', modified = NOW() WHERE oauth_provider = '".$userData['oauth_provider']."' AND oauth_uid = '".$userData['oauth_uid']."'";
                $update $this->db->query($query);
            }else{
                // Insert user data
                $query "INSERT INTO ".$this->userTbl." SET oauth_provider = '".$userData['oauth_provider']."', oauth_uid = '".$userData['oauth_uid']."', first_name = '".$userData['first_name']."', last_name = '".$userData['last_name']."', email = '".$userData['email']."', locale = '".$userData['locale']."', picture = '".$userData['picture']."', link = '".$userData['link']."', created = NOW(), modified = NOW()";
                $insert $this->db->query($query);
            }
            
            // Get user data from the database
            $result $this->db->query($prevQuery);
            $userData $result->fetch_assoc();
        }
        
        // Return user data
        return $userData;
    }
}

Site Settings and API Configuration (config.php)

The database settings and LinkedIn API configuration constant variables are defined in the config.php file.
Database Constants:

  • DB_HOST – Specify the database host.
  • DB_USERNAME – Specify the database username.
  • DB_PASSWORD – Specify the database password.
  • DB_NAME – Specify the database name.
  • DB_USER_TBL – Specify the table name where the user’s account data will be stored.

LinkedIn API Constants:

  • LIN_CLIENT_ID – Specify the LinkedIn App ID.
  • LIN_CLIENT_SECRET – Specify the LinkedIn App Secret.
  • LIN_REDIRECT_URL – Specify the OAuth Callback URL.

Call LinkedIn API:
The PHP OAuth library is used to connect with LinkedIn API and working with OAuth client.

<?php
/*
 * Basic Site Settings and API Configuration
 */

// Database configuration
define('DB_HOST''MySQL_Database_Host');
define('DB_USERNAME''MySQL_Database_Username');
define('DB_PASSWORD''MySQL_Database_Password');
define('DB_NAME''MySQL_Database_Name');
define('DB_USER_TBL''users');

// LinkedIn API configuration
define('LIN_CLIENT_ID''Insert_LinkedIn_App_ID');
define('LIN_CLIENT_SECRET''Insert_LinkedIn_App_Secret');
define('LIN_REDIRECT_URL''OAuth_Callback_URL');
define('LIN_SCOPE''r_liteprofile r_emailaddress'); //API permissions

// Start session
if(!session_id()){
    session_start();
}

// Include the oauth client library
require_once 'linkedin-oauth-client-php/http.php';
require_once 'linkedin-oauth-client-php/oauth_client.php';

Note that: You’ll find the Client ID and Client Secret on your LinkedIn App settings page.

Login & Get LinkedIn Account Data (index.php)

In this file, the LinkedIn API authentication process is handled using PHP.

  • Initially, the authentication URL is generated and LinkedIn Sign-in button is displayed on the web page.
  • If the user authenticates with their LinkedIn account, the following happens:
    • The profile information is retrieved from the LinkedIn account using LinkedIn Profile API v2 (https://api.linkedin.com/v2/me) and PHP.
    • Call the LinkedIn API to get the member’s email address (https://api.linkedin.com/v2/emailAddress).
    • Insert account data in the database using checkUser() function of User class.
    • The user’s account info is stored in the SESSION.
    • The LinkedIn profile details (OAuth ID, First Name, Last Name, Email, Picture, Link, etc.) is displayed on the webpage.
<?php
// Include configuration file
require_once 'config.php';

// Include User class
require_once 'User.class.php';

$authUrl $output '';

// If user already verified 
if(isset($_SESSION['oauth_status']) && $_SESSION['oauth_status'] == 'verified' && !empty($_SESSION['userData'])){
    // Retrieve user's profile data from session
    $userData $_SESSION['userData'];
    
    // Prepare output to show LinkedIn profile data
    if(!empty($userData)){
        $output  '<h2>LinkedIn Profile Details</h2>';
        $output .= '<div class="ac-data">';
        $output .= '<img src="'.$userData['picture'].'"/>';
        $output .= '<p><b>LinkedIn ID:</b> '.$userData['oauth_uid'].'</p>';
        $output .= '<p><b>Name:</b> '.$userData['first_name'].' '.$userData['last_name'].'</p>';
        $output .= '<p><b>Email:</b> '.$userData['email'].'</p>';
        $output .= '<p><b>Logged in with:</b> LinkedIn'.'</p>';
        $output .= '<p><b>Profile Link:</b> <a href="'.$userData['link'].'" target="_blank">Click to visit LinkedIn page</a></p>';
        $output .= '<p><b>Logout from</b> <a href="logout.php">LinkedIn</a></p>';
        $output .= '</div>';
    }
}elseif((isset($_GET["oauth_init"]) && $_GET["oauth_init"] == 1) || (isset($_GET['oauth_token']) && isset($_GET['oauth_verifier'])) || (isset($_GET['code']) && isset($_GET['state']))){
    $client = new oauth_client_class;
    
    $client->client_id LIN_CLIENT_ID;
    $client->client_secret LIN_CLIENT_SECRET;
    $client->redirect_uri LIN_REDIRECT_URL;
    $client->scope LIN_SCOPE;
    $client->debug 1;
    $client->debug_http 1;
    $application_line __LINE__;
    
    if(strlen($client->client_id) == || strlen($client->client_secret) == 0){
        die('Please go to LinkedIn Apps page https://www.linkedin.com/secure/developer?newapp= , '.
            'create an application, and in the line '.$application_line.
            ' set the client_id to Consumer key and client_secret with Consumer secret. '.
            'The Callback URL must be '.$client->redirect_uri.'. Make sure you enable the '.
            'necessary permissions to execute the API calls your application needs.');
    }
    
    // If authentication returns success
    if($success $client->Initialize()){
        if(($success $client->Process())){
            if(strlen($client->authorization_error)){
                $client->error $client->authorization_error;
                $success false;
            }elseif(strlen($client->access_token)){
                $success $client->CallAPI(
                    'https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))', 
                    'GET', array(
                        'format'=>'json'
                    ), array('FailOnAccessError'=>true), $userInfo);
                $emailRes $client->CallAPI(
                    'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))', 
                    'GET', array(
                        'format'=>'json'
                    ), array('FailOnAccessError'=>true), $userEmail);
            }
        }
        $success $client->Finalize($success);
    }
    
    if($client->exit) exit;
    
    if(strlen($client->authorization_error)){
        $client->error $client->authorization_error;
        $success false;
    }
    
    if($success){
        // Initialize User class
        $user = new User();
        
        // Getting user's profile data
        $inUserData = array();
        $inUserData['oauth_uid']  = !empty($userInfo->id)?$userInfo->id:'';
        $inUserData['first_name'] = !empty($userInfo->firstName->localized->en_US)?$userInfo->firstName->localized->en_US:'';
        $inUserData['last_name']  = !empty($userInfo->lastName->localized->en_US)?$userInfo->lastName->localized->en_US:'';
        $inUserData['email']      = !empty($userEmail->elements[0]->{'handle~'}->emailAddress)?$userEmail->elements[0]->{'handle~'}->emailAddress:'';
        $inUserData['picture']    = !empty($userInfo->profilePicture->{'displayImage~'}->elements[0]->identifiers[0]->identifier)?$userInfo->profilePicture->{'displayImage~'}->elements[0]->identifiers[0]->identifier:'';
        $inUserData['link']       = 'https://www.linkedin.com/';

        // Insert or update user data to the database
        $inUserData['oauth_provider'] = 'linkedin';
        $userData $user->checkUser($inUserData);
        
        //Storing user data into session
        $_SESSION['userData'] = $userData;
        $_SESSION['oauth_status'] = 'verified';
        
        //Redirect the user back to the same page
        header('Location: ./');
    }else{
         $output '<h3 style="color:red">Error connecting to LinkedIn! try again later!</h3><p>'.HtmlSpecialChars($client->error).'</p>';
    }
}elseif(isset($_GET["oauth_problem"]) && $_GET["oauth_problem"] <> ""){
    $output '<h3 style="color:red">'.$_GET["oauth_problem"].'</h3>';
}else{
    $authUrl '?oauth_init=1';
    
    // Render LinkedIn login button
    $output '<a href="?oauth_init=1"><img src="images/linkedin-sign-in-btn.png"></a>';
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Login with LinkedIn using PHP by CodexWorld</title>
    
    <!-- Include stylesheet file -->
    <link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<div class="container">
    <div class="in-box">
        <!-- Display login button / profile information -->
        <?php echo $output?>
    </div>
</div>
</body>
</html>

Logout (logout.php)

If the user wishes to log out from their LinkedIn account, the logout.php file is loaded.

  • Remove OAuth status and user data from the SESSION.
  • Redirect the user to the homepage.
<?php
// Start session
if(!session_id()){
    session_start();
}

// Unset token and user data from session
unset($_SESSION['oauth_status']);
unset($_SESSION['userData']);

// Destroy entire session
session_destroy();

// Redirect to homepage
header("Location:index.php");
exit;
?>

Login with LinkedIn in CodeIgniter

Conclusion

As per the LinkedIn developer program updates, all the developer needs to migrate APIs to Version 2.0 with OAuth 2.0 by May 1, 2019. If you integrated LinkedIn Login in the web site, your authentication code needs to be updated with LinkedIn API v2 and OAuth 2.0. Our example code helps you to integrate the login system with LinkedIn API v2 using PHP. To make the LinkedIn login more user-friendly, you can use JavaScript SDK to integrate LinkedIn Login without page refresh using JavaScript.

Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request

31 Comments

  1. DT Said...
  2. DT Said...
  3. HymedGH Said...
  4. Bilal Said...
  5. Chethan Said...
  6. Sebastian M. Said...
  7. Mehul Said...
    • CodexWorld Said...
  8. Ketan Said...
  9. Ketan Said...
  10. Geoff Said...
  11. Anik Hasibul Said...
  12. Amrita Said...
  13. Paulpremkumar Said...
  14. Paulpremkumar Said...
  15. Meow Said...
  16. Gurmukh Singh Said...
  17. Steve Jeong Said...
    • CodexWorld Said...
  18. Aniket Said...
  19. Samuel Said...
  20. Bill Said...
  21. Tiffany Said...
  22. Ashu Said...
  23. Ashu Said...
  24. Deepanshu Said...
  25. Usman Said...
  26. Usman Said...
  27. Usman Said...
    • CodexWorld Said...

Leave a reply

keyboard_double_arrow_up