passport

path: courses/express-node/passport.md

- **fileName**: passport
- **Created on**: 2024-07-13 10:32:33

installation

npm i passport passport-local express-session 

the main function config


export default function initExpress(express, app) {
	app.use(express.json());
	app.use(express.urlencoded({ extended: true }));
	app.use(cors());
	setDbSessions(app, process.env.DB_URL); // setting some config for db

  // maddleware for debugging
  app.use((req, res, next) => {
    console.log(" ----------------------------------- ");
    console.log('Session:', req.session);
    console.log(" ----------------------------------- ");
    next();
  });

	app.get("/welcome", isAuth, (req, res) => {
    console.log(req.session);
		res.send("<h1> welcome boss </h1>");
	});

	app.post("/pass-login", passport.authenticate("local"), (req, res) => {
		console.log(req.session);
		res.send("<h1> welcome from auth password login </h1>");
	});
}


setting for the session and passport and db

function setDbSessions(app, url) {
  mongoose.connect(url,{}).catch(error => console.log("App.js mongoose.connect error",error));
  let db = mongoose.connection;
  db.on('error', console.error);
  db.once('open', function(){
    console.log("App is connected to DB", db.name)
  }); // settting db settings

  app.use(session({
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    store: MongoStore.create({
      client: mongoose.connection.getClient() 
    }),
    cookie: {
      maxAge: 1000 * 60 * 60 * 24 
    },
  }));
	app.use(passport.initialize());
	app.use(passport.session());
	passport.use(localStratage);
}

passport.initialize() - This creates middleware that runs before every HTTP request. It works in two steps:

Checks to see if the current session has a req.session.passport object on it. This object will be

{ user: '' }
  1. If it finds a session with a req.session.passport property, it grabs the User ID and saves it to an
    internal Passport method for later.
passport.session() - This calls the Passport Authenticator using the "Session Strategy". Here are the basic steps that this method takes:

Takes the MongoDB user ID obtained from the passport.initialize() method (run directly before) and passes
it to the passport.deserializeUser() function (defined above in this module). The passport.deserializeUser()
function will look up the User by the given ID in the database and return it.
If the passport.deserializeUser() returns a user object, this user object is assigned to the req.user property
and can be accessed within the route. If no user is returned, nothing happens and next() is called.

db-session.md -> check for session and db

passport strategy file

import { Strategy } from "passport-local";
import { comparePassword } from "./bcrypt.mjs";
import { User } from "../dbScheme/UserScheme.mjs";
import passport from "passport";

const customFields = {
  username: 'username',
  password: 'password',
};

const checkValidFields = (username, password, done) => {
  User.findOne({ username: username }) // check if the user found or not
    .then((user) => {
      if (!user) return done(null, false); 
      const match = comparePassword(password, user.password); // check for password hash and password
      if (match) {
        return done(null, user); // passing the user to serializeUser
      }else {
        return done(null, false);
      }
    })
    .catch((err) => { 
      console.log(err);
      done(err); 
    });
};

passport.serializeUser((user, done) => {
    done(null, user.id); // passing the user.id to deserializeUser
});

passport.deserializeUser((userId, done) => {
  User.findById(userId) // check if user found or not 
    .then((user) => {
      done(null, user); adding user to req
    })
    .catch(err => done(err))
});

const localStratage = new Strategy(customFields, checkValidFields);
export default localStratage;

Custom Fields Configuration

This object defines the fields that Passport will look for in the request. By default, Passport looks for username and password fields, but you can customize them as needed.

Authentication Logic

Serialize User

This function determines which data of the user object should be stored in the session. Here, only the user's ID is stored.

Deserialize User

This function is used to retrieve the full user object from the session data. When a request is made, Passport will use the ID stored in the session to find the user in the database and attach the user object to the req object.


isAuth function for check for auth user

export const isAuth = (req, res, done) => {
  console.log(req.session);
	if (req.isAuthenticated()) { // check for auth user
		done();
	} else {
		res.status(404).send("<h1> not authorzation user </h1>");
	}
};

this output object come pass-login end point

Session {
  cookie: {
    path: '/',
    _expires: 2024-07-14T11:27:14.100Z,
    originalMaxAge: 86400000,
    httpOnly: true
  },
  passport: { user: '66925ade46279d6d21a6491e' }
}

**after finish the passport login success adding the passport key to session and adding to the request user req.user **

check for another way to auth the user jwt.md

continue:bcrypt.md
before:db-session.md