← Back to list

Configuring local and social authentication using passsport.js

Articles of this series

Noble Mathew in Dev Genius · 2025-01-21 10:57 · 3 claps · 5.0 min read
#google-auth #passportjs #mongodb #nodejs
Open on Medium ↗
Wiki topics: 🌐 · Web Development 🔒 · Cybersecurity

Configuring local and social authentication using passsport.js

Articles of this series

In order to keep the articles short and concise, we are splitting this topic in to a three part series.

  1. Configuring nodeJS With typescript
  2. Configuring MongoDB
  3. Configuring local and social authentication using passsport.js

Passport.js is a powerful and flexible authentication middleware for Node.js. It simplifies the process of adding user authentication to your web applications.

The benefits of passport js includes

  • Reduced Development Time: Streamlines authentication implementation.
  • Improved Security: Leverages best practices for secure authentication.
  • Enhanced User Experience: Provides smooth and consistent authentication flows.

So lets start with installing passport. For this tutorial we are implementing local authentication with passport. Also in this article we will check about how to wrap the queries

So lets start with installation. The following command will install passport and other related plugins needed for configuring the authentication.

npm install passport passport-local express-session body-parser connect-mongo passport-google-oauth20 bcrypt

Next lets initialize it. Before initializing we have to define the strategy that we are going to use for login. Here we are creating 2 strategies local and google. Other available strategies are available here https://www.passportjs.org/packages/

So we are going to create a context modal user that will be shared acros all the resolvers. Create file /graphql/modals/i-user.ts

export interface IUser {
    id: string,
    name: string,
    email: string

}

So we are going to create a a helper file which we are going to use across all the strategies. Create file /login_strategy/helpers.ts

import MongoStore from "connect-mongo";
import { IUser } from "../graphql/modals/i-user";
import config from './../loadConfig.js';

export const passportSerializer = (user: IUser, cb) => {
    process.nextTick(function() {
      return cb(null, {
        id: user.id,
        name: user.name,
        email: user.email
      });
    });
  }

  export const passportDeserializer = (user: IUser, cb) => {
    process.nextTick(function() {
      return cb(null, user);
    });
  }

  export const sessionConfig = {
    secret: 'keyboard cat',
    resave: false,
    saveUninitialized: false,
    cookie: { secure: false },
    store: MongoStore.create({
      mongoUrl: config.db.mongo.url,
      collectionName: "sessions",
      stringify: false,
      autoRemove: "interval",
      autoRemoveInterval: 1
    }) 
}

Now it is time to create the strategies.

/login_strategy/local.ts


import { Strategy as LocalStrategy } from 'passport-local';
import { User } from '../repository/mongoDb/user';
import bcrypt from 'bcrypt';
import { v4 as uuid } from 'uuid';

const strategy = new LocalStrategy(
    {
      usernameField: 'email',
      passwordField: 'password',
    },
    async (email, password, done) => {
      const user = await User.find({ email: email }).findOne();
      if (!user) return done(null, false);
      const match  = await bcrypt.compare(password, user.password);
      if (!match) return done(null, false);
      return done(null, user);
    }
)

export const createNewUser = async (req, res) => {
  // Access data from the request body
  const { name, email, password } = req.body;

  // Basic input validation (you should add more robust checks)
  if (!name || !email || !password) {
    return res.status(400).json({ error: 'Missing required fields' });
  }

  const hashedPassword = bcrypt.hashSync(password, 10);

  const newUser = new User({
    id: uuid(),
    name: name,
    email: email,
    password: hashedPassword,
    provider: 'local',
    providerId: ''
  });

  await newUser.save();

  res.status(201).json({ message: 'User created successfully', status: true });
}

export default strategy;

/login_strategy/google.ts

import { Strategy } from "passport-google-oauth20";
import { v4 as uuid } from 'uuid';
import { User } from "../repository/mongoDb/user";
import config from '../loadConfig.js';

const strategy = new Strategy({
    clientID: config.auth.google.GOOGLE_CLIENT_ID,
    clientSecret: config.auth.google.GOOGLE_CLIENT_SECRET,
    callbackURL: config.auth.google.callbackURL,
  },
  async function verify(accessToken, refreshToken, profile, cb) {
    console.log('inside stragey', accessToken, refreshToken, profile)
    const user = await User.find({ providerId: profile.id}).findOne();
    if (user && user.id) {
      return cb(null, user);
    } else {
      const newUser = new User({
        id: uuid(),
        name: profile.displayName,
        email: profile.emails?.[0]?.value,
        password: uuid(),
        provider: 'google',
        providerId: profile.id
      });
      const user = await newUser.save();
      return cb(null, user)
    }
  }
);

export default strategy;

To integrate with google auth, you need to create a OAuth client and get the credentials. Update the credentials in the config file. For the callback url, you can set any url where google will redirect after successful authentication. For this tutorial we are giving http://127.0.0.1:4000/auth/google/callback

Use the below link to more info on the same.

[embed]Integrating Google Sign-In into your web app | Authentication | Google for Developers Warning: The Google Sign-In library optionally uses FedCM APIs, and their use will become a requirement. Conduct an…developers.google.com

Lets modify the user resolver to return the currently logged in user.

import { User } from "../../repository/mongoDb/user.js";
import { Resolvers } from "../modals/generated/user.js";
import { v4 as uuid } from 'uuid';

export const resolvers: Resolvers = {
  Query: {
    currentUser: (parent, args, context) => {
      // we will inject the context with current user info 
      // so all functiona can use the current login info

      return context.user;
    },
    users: async (parent, args, context) => {
      return await User.find({});
    },
  },
  // We can remove the mutation here as we are doing the sign up not using 
  // graphl as we are making the graphql authenticated. 
}

Now since we created all this necessary files, lets connect all this in the index.ts

import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import mongoose from 'mongoose';
import schema from './graphql/schema.js';
import express from 'express';
import cors from 'cors';
import session from 'express-session';
import passport from 'passport';
import { IUser } from './graphql/modals/i-user.js';
import localStrategy, { createNewUser } from './login_strategy/local.js';
import googleStrategy from './login_strategy/google.js';
import http from 'http';
import bodyParser from 'body-parser';
import { GraphQLError } from 'graphql';
import config from './loadConfig.js';
import { passportSerializer, passportDeserializer, sessionConfig } from './login_strategy/helpers.js';
import { GraphqlContext } from './graphql/modals/graphql_context.js';

declare global {
  namespace Express {
    interface User extends IUser {}
  }
}

mongoose
    .connect(config.db.mongo.url, {})
    .then(() => {
        console.log(`Db Connected`);
    })
    .catch(err => {
        console.log(err.message);
    });

// Required logic for integrating with Express
// configure session and related params
const app = express();
const httpServer = http.createServer(app);
app.use(express.urlencoded({ extended: false }));
app.use(session(sessionConfig));
passport.serializeUser(passportSerializer);
passport.deserializeUser(passportDeserializer);

//Define login strategies
passport.use(localStrategy);
passport.use(googleStrategy);
passport.use(microsoftStrategy);

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

// // Same ApolloServer initialization as before, plus the drain plugin
// // for our httpServer.
const server = new ApolloServer<GraphqlContext>({
    schema,
});

await server.start();

// Routes for each login scenarios
// local auth
app.post('/login', 
  passport.authenticate('local', { failureRedirect: '/loginFailure' }),
  function(req, res) {
    res.json({message:"Success", user: req.user });
  }
);
app.post('/signup', createNewUser);

// google Auth
app.get('/auth/google',
  passport.authenticate('google', { scope: ['profile', 'email'] }));

app.get('/auth/google/callback',
  passport.authenticate('google', { failureRedirect: '/loginFailure' }),
  function(req, res) {
    // Successful authentication, redirect home.
    console.log(req.session, req.user)
    res.redirect('/');
  }
);

// Set up our Express middleware to handle CORS, body parsing,
// and our expressMiddleware function.
app.use(
  '/',
  cors(),
  bodyParser.json({}),
  expressMiddleware(server, {
    context: async ({ req, res }) => {
      // we could also check user roles/permissions here.
      // This will make the entire graphql authenticated. 
      // If you don't want to this, you can completely remove this 
      // middleware
      const user = req.user;

      if (!user || !user.id) {
        // throwing a `GraphQLError` here allows us to specify an HTTP status code,
        // standard `Error`s will have a 500 status code by default
        throw new GraphQLError('User is not authenticated', {
          extensions: {
            code: 'UNAUTHENTICATED',
            http: { status: 401 },
          },
        });
      }
      return { user }
    },
  }),
);

const PORT = config.port || 4000;
await new Promise((resolve) => httpServer.listen({ port: PORT }));

If we run the application now, we have the following end points which will access form-date ( used for auth ) and completed authenticated graphQl.

Few request samples to create and login using local authentication.

Create a Local User
==================
POST /signup
Content-Type: application/x-www-form-urlencoded

Body
email: "example@example.com"
password: "password"
name: "Noble"

Login as Local User
===================
POST /login
Content-Type: application/x-www-form-urlencoded

Body
email: "example@example.com"
password: "password"

Google Login / Sign Up
GET /auth/google

Full codebase is available in repo

https://github.com/rock-o/nodejs-graphql-starter


메타데이터
post_id
ee6085e7dd8a
slug
configuring-local-and-social-authentication-using-passsport-js-ee6085e7dd8a
url
https://blog.devgenius.io/configuring-local-and-social-authentication-using-passsport-js-ee6085e7dd8a
canonical_url
https://blog.devgenius.io/configuring-local-and-social-authentication-using-passsport-js-ee6085e7dd8a
author_url
https://medium.com/@noble.m
status
ok
fetched_at
2026-06-15 20:49:13