Skip to main content

LinkedIn Login using Node JS and passport

Passport is an authentication middleware for Node, which authenticates requests and delegates all other functionality to the application. Considering the unique application requirements, Passport has stuck to authentication mechanisms known as strategies. In the blog, we will be implementing a similar strategy for Login with Linkedin.

Pre -Requisites:

  1. Basic Knowledge of NodeJS
  2. Node JS should be installed on your system.

Steps to configure

  1. Creating Linkedin APP_ID and APP_SECRET
  2. Go to https://www.linkedin.com/developers/ and login with your Linkedin account.
  3. Once you have registered, click on the create app link and add the required details to create an app

Create Linkedin APP

Provide basic details about your app:

  • App name
  • Company
  • Privacy policy URL
  • Business email
  • App logo

    • After creating apps go to the auth tab in the navigation bar as shown below. You can now copy your secret and ID from here

    App ID and Secret

  • Now enough, let's move to code, First of all, create a directory named Linkedin-node-authentication

    mkdir Linkedin-node-authentication
  • Move to the directory Linkedin-node-authentication/
  cd Linkedin-node-authentication
  1. In the root create a file package.json and copy the following code

The dependencies, we are going to use in the projects are

{
  "name": "linkedin-login-node",
  "version": "1.0.0",
  "description": "Basic application for setting up Linkedin login using node and passport",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "author": "LoginRadius",
  "license": "ISC",
  "dependencies": {
    "ejs": "^3.1.2",
    "express": "^4.17.1",
    "express-session": "^1.17.1",
    "passport": "^0.4.1",
    "passport-linkedin-oauth2": "^2.0.0"
  }
}
  1. After this run the following command in the terminal

    npm install
  2. Now create a file named server.js and paste the following code
const express = require('express');
const app = express();
const session = require('express-session');
const passport = require('passport');
const LinkedInStrategy = require('passport-linkedin-oauth2').Strategy;
const routes = require('./routes.js');
const config = require('./config')

app.set('view engine', 'ejs');

app.use(session({
  resave: false,
  saveUninitialized: true,
  secret: 'SECRET'
}));

app.use(passport.initialize());
app.use(passport.session());

passport.serializeUser(function (user, cb) {
  cb(null, user);
});

passport.deserializeUser(function (obj, cb) {
  cb(null, obj);
});

passport.use(new LinkedInStrategy({
  clientID: config.linkedinAuth.clientID,
  clientSecret: config.linkedinAuth.clientSecret,
  callbackURL: config.linkedinAuth.callbackURL,
  scope: ['r_emailaddress', 'r_liteprofile'],
}, function (token, tokenSecret, profile, done) {
  return done(null, profile);
}
));

app.use('/', routes);

const port = 3000;

app.listen(port, () => {
  console.log('App listening on port ' + port);
});
  1. Now create a file named routes.js in the root directory and paste the following code
const passport = require('passport');
const express = require('express');
var router = express.Router();

router.get('/', function (req, res) {
  res.render('pages/index.ejs'); // load the index.ejs file
});

router.get('/profile', isLoggedIn, function (req, res) {
  res.render('pages/profile.ejs', {
    user: req.user // get the user out of session and pass to template
  });
});

router.get('/auth/linkedin', passport.authenticate('linkedin', {
  scope: ['r_emailaddress', 'r_liteprofile'],
}));

router.get('/auth/linkedin/callback',
  passport.authenticate('linkedin', {
    successRedirect: '/profile',
    failureRedirect: '/login'
  }));

router.get('/logout', function (req, res) {
  req.logout();
  res.redirect('/');
});


function isLoggedIn(req, res, next) {
  if (req.isAuthenticated())
    return next();
  res.redirect('/');
}

module.exports = router;
  1. Create a directory views and under this create a directory named pages. Under this folder create two pages named profile.ejs and index.ejs
// index.ejs
<!doctype html>
<html>

<head>
  <title>Linkedin Node Authentication</title>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
  <link rel="stylesheet" type="text/css"
    href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
  <style>
    .linkedin {
      background-color: #0073b1 !important;
      color: #fff !important;
    }
    .fa-linkedin-f:before,
    .fa-linkedin:before {
      content: "\f0e1";
    }
  </style>
</head>

<body>
  <nav class="light-blue lighten-1" role="navigation">
    <div class="nav-wrapper container">
      <a id="logo-container" href="#" class="brand-logo">Node Authentication</a>
    </div>
  </nav>
  <div class="section no-pad-bot" id="index-banner">
    <div class="container">
      <br><br>
      <div class="row center">
        <div class="col s6 offset-s3">
          <div class="card">
            <div class="card-content">
              <span class="card-title">Linkedin Login using Node and passport</span>
            </div>
            <div class="card-action">
              <a href="/auth/linkedin" class="waves-effect waves-light btn social linkedin">
                <i class="fa fa-linkedin"></i> Sign in with Linkedin
              </a>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>
<!- profile.ejs->
<!doctype html>
<html>

<head>  
  <title>LinkedIn Node Authentication</title>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link rel="stylesheet" type="text/css"
    href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.5/css/materialize.min.css">
  <style>
    .card:hover {
      box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
      margin-bottom: 54px;
    }
  </style>
</head>

<body>
  <nav class="light-blue lighten-1" role="navigation">
    <div class="nav-wrapper container">
      <a id="logo-container" href="#" class="brand-logo">Node Authentication</a>
      <a href="/logout" class="right">Logout</a>
    </div>
  </nav>
  <div class="section no-pad-bot" id="index-banner">
    <div class="container">
      <br><br>
      <div class="row center">
        <div class="col s12">
          <div class="card">
            <div class="card-content blue lighten-3">
              <span class="card-title white-text"><strong><i class="large material-icons">person</i>
                </strong></span>
            </div>
            <div class="card-action">
              <h5><b><%= user.displayName %></b></h5>
              <p><strong>Linkedin id</strong>: <%= user.id %></p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>

</html>
  1. Finally, when you are done with the above code you can now write all your app details gathered in step 1 to config.js file created in the root directory
module.exports = {
  'linkedinAuth': {
    'clientID': '<CLIENT_ID>', // your App ID
    'clientSecret': '<CLIENT_SECRET>', // your App Secret
    'callbackURL': 'http://127.0.0.1:3000/auth/linkedin/callback'
  }
}
  1. Let's have a final check with the repository, aftre follwoing all the steps in the same pordr the directory structure of your code will look like below:
// Final directory structure
Linkedin-node-authentication/
  --|node_modules
  --|views/
    |--|pages/
    |----|error.ejs
    |----|profile.ejs
    |----|index.ejs
  --|config.js
  --|package.json
  --|package-lock.json
  --|routes.js
  --|server.js
  1. Now run the server by executing below command in the directory Linkedin-node-authentication/
npm start
  1. Visit the browser with the URL http://localhost:3000

Linkedin login home page

Click on the sign in button, and you will be asked to login through Linkedin. Once logged in you will be redirected to profile page as below:

Comments

Popular posts from this blog

How to use Ngx-Charts in Angular ?

Charts helps us to visualize large amount of data in an easy to understand and interactive way. This helps businesses to grow more by taking important decisions from the data. For example, e-commerce can have charts or reports for product sales, with various categories like product type, year, etc. In angular, we have various charting libraries to create charts.  Ngx-charts  is one of them. Check out the list of  best angular chart libraries .  In this article, we will see data visualization with ngx-charts and how to use ngx-charts in angular application ? We will see, How to install ngx-charts in angular ? Create a vertical bar chart Create a pie chart, advanced pie chart and pie chart grid Introduction ngx-charts  is an open-source and declarative charting framework for angular2+. It is maintained by  Swimlane . It is using Angular to render and animate the SVG elements with all of its binding and speed goodness and uses d3 for the excellent math functio...

Understand Angular’s forRoot and forChild

  forRoot   /   forChild   is a pattern for singleton services that most of us know from routing. Routing is actually the main use case for it and as it is not commonly used outside of it, I wouldn’t be surprised if most Angular developers haven’t given it a second thought. However, as the official Angular documentation puts it: “Understanding how  forRoot()  works to make sure a service is a singleton will inform your development at a deeper level.” So let’s go. Providers & Injectors Angular comes with a dependency injection (DI) mechanism. When a component depends on a service, you don’t manually create an instance of the service. You  inject  the service and the dependency injection system takes care of providing an instance. import { Component, OnInit } from '@angular/core'; import { TestService } from 'src/app/services/test.service'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.compon...

How to solve Puppeteer TimeoutError: Navigation timeout of 30000 ms exceeded

During the automation of multiple tasks on my job and personal projects, i decided to move on  Puppeteer  instead of the old school PhantomJS. One of the most usual problems with pages that contain a lot of content, because of the ads, images etc. is the load time, an exception is thrown (specifically the TimeoutError) after a page takes more than 30000ms (30 seconds) to load totally. To solve this problem, you will have 2 options, either to increase this timeout in the configuration or remove it at all. Personally, i prefer to remove the limit as i know that the pages that i work with will end up loading someday. In this article, i'll explain you briefly 2 ways to bypass this limitation. A. Globally on the tab The option that i prefer, as i browse multiple pages in the same tab, is to remove the timeout limit on the tab that i use to browse. For example, to remove the limit you should add: await page . setDefaultNavigationTimeout ( 0 ) ;  COPY SNIPPET The setDefaultNav...