Authentication using PassportJS

Authentication using PassportJS

Passport strategy for authenticating using Github

  • Quick Introduction to PassportJS
  • Requirements
  • Guide on setup

Here is a working example

What is PassportJS?

Passportjs is an authentication middleware for Node.js. A comprehensive set of strategies support authentication using username and password, facebook, Twitter, and more. For more, Go here

For websites supporting both email and social provider logins, almost 50% of users will choose a social provider to log in. In this quick guide, I'm going to outline how to add a quick register/login using Github-strategy

Requirements :

  1. Basic knowledge of JavaScript and NodeJs
  2. NodeJs installed.

Guide on setup :

1. Installing dependencies :

npm install express mongoose passport ejs passport-github express-session

2 Create a folder server.js and initialize server :

   const express = require("express") 
   const app = express()
   app.set("view engine", "ejs")

   app.get("/", (req, res) => {
       res.render("dashboard")
   })
    app.listen(3000, (req, res) => {
         console.log("App is listening at port 3000")
    })

3 Require mongoose and establish a connection with the database

  const mongoose = require("mongoose")

  monogoose.connect("mongodb://localhost:27017/passport_authentication", (err) =>{ 
      if(err) throw err;
      console.log("Database connection established successfully
   })

4 Create a models folder in the root directory and then, create a file user.js

5 Create the User model :

     const mongoose = require("mongoose")

     const userSchema = new mongoose.Schema({
         name : String,
         clientId : Number
    })

6 Register Application on Github and obtain your clientId and clientSecret

  • Open your Github account and go to settings

settings.png

  • Go to Developers settings

developerSetting.png

  • Click on New Oauth App to create a new app

newOauthApp.png

  • Click on Generate new Client Secret

generateNewClientSecret.png

  • Copy the ClientId and ClientSecret and save in the .env file.

copyClientIdandSecret.png

-Finally, enter the home url and callback url as seen below.

updateApplication.png

7 In the server.js file, require passport and passport-github and then set up a new GithubStrategy.

A strategy accepts 2 arguments :

  • An Object containing : Client Id, Client Secret and callbalk Url
  • A function to be called when a user is successfully authenticated.
   const passport = require("passport")
   const GithubStrategy = require("passport-github)


    passport.use(new GitHubStrategy({
      clientID: process.env.clientID,
      clientSecret: process.env.clientSecret,
      callbackURL: process.env.callbackURL
     },
     function(accessToken, refreshToken, profile, done) {
        console.log(profile)
        User.findOne({clientID : profile.id}, async (err, user) => {
      if(err) throw err

      if(user !== null) {
         done(null, profile)
      } else {
          const newUser = await new User({
          name : profile.displayName,
          clientId : profile.id
      })
          newUser.save((err, user) => {
          if(err) throw err
      })
         done(null, profile)
         }
      })
     }
   ));

8 Set up the express-session.

    app.use(session({
       secret: "muanya",
       resave: false,
       saveUninitialized: false,
       cookie: { 
          httpOnly : true,
          secure: false
        }
   }));

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

9 Serialize user into the session, and deserialize when subsequent requests are made.

To serialize an object means to convert its content into a small key that can be deserialized into the original object

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

   passport.deserializeUser(function(id, done) {
        done(null, id);
   });

10 Create the routes for calling '/auth/github' and '/auth/github.callback'

      app.get('/failure', (req, res) => {
         res.render("failure")
      })

      app.get('/auth/github', passport.authenticate("github"))

      app.get("/auth/github/callback", 
          passport.authenticate("github", { failureRedirect "/failure"}), 
          (req, res) => {
             res.redirect("/")
      })

11 Finally, create a middleware authentification function that checks if the user is stored into the session and then update the app.get("/", ...)

const isAuthenticated = (req, res, next) => {
    if(req.user) {
       next()
    } else {
        res.redirect("login")
      }
   }


 app.get("/", isAuthenticated, (req, res) => {
      console.log(req.user)
      User.findOne({clientID : req.user}, (err, user) => {
        if(err) throw err
        res.render("home", {user : user})
     })
})

Now, you've successfully setup authentication using Github strategy.

Below is the session passport flow:

Github seesion flow.png

LoggedIn user passport flow.png