loading...
Cover image for Building a NodeJS Web App Using PassportJS for Authentication

Building a NodeJS Web App Using PassportJS for Authentication

gm456742 profile image Richard Debrah Originally published at github.com ・13 min read

Updated!!!
This tutorial uses PassportJS to authenticate the NodeJS App with MySQL Database Management Software (DBMS). The reason for this article is just simple. While i was studying web development i was faced with a challenge when i was working on my second project to integrate PassportJS Authentication into my app. At that time i was using MySQL for database management, SequelizeJS which is an Object Relation Mapper(ORM) for SQL-based databases, in this case MySQL, ExpressJS middleware, Body Parser and Express Session for server and session management. The difficulty was that i could only find tutorials that used Handlebars as the ORM and MongoDB as the DBMS which at that time, i was not that familiar with so if you find yourself at this crossroad this is for you. I will not waste your time but dive into it right away. I will be as literal as i can possibly be so even the least knowledged in web development can understand. We will need to make a few things ready for this setup. I am using a Windows Pc so please find a workaround if anything i say does not work for your OS especially my recommendations but the process is the same i believe.

First of all you will need to have a computer with your favorite text editor (I used VS Code), a web browser (I recommend Google Chrome), your favorite terminal (Git Bash recommended) and a SQL DBMS of your choice. I am using MySQL Workbench 6.3 CE. I will go through the steps in a list so it is easy to follow. When you have all the above, and properly set up, follow the instructions below. I am assuming you already have your database created, if not I will take you through.

  1. Create a folder on your computer in any location of your choice. I prefer to navigate to my preferred location using my terminal and then typing mkdir nameOfProject. I will create the folder learningPassportJS on my desktop for this tutorial. Next is to type cd nameOfProject to navigate into the project folder.

  1. In the terminal we will have to initialize the folder to handle all our NodeJS framework. You can decide to do this later on but i recommend you doing this first if you are new to this process. Do this by typing npm init and press enter. This sets up your project with a package.json file. This file will contain the information including all the expected dependencies and licenses as well as your name. For our purpose i will just keep pressing enter on my keyboard to load defaults but I will set the entry point as server.js. Feel free to change it to what pleases you. Please make sure you have lowercase letters in your texts or you will have to type them yourself.

  1. After we have initialized our project we will create our server.js file with touch server.js on the terminal.

  2. Let us now install all the dependencies we will require. I will explain why we need each one later but i like to install all to get it out of the way. You can always install them later but you need them to run the app successfully. Install them in one line as npm i --save sequelize passport passport-local mysql2 mysql express express-session body-parser bcrypt-nodejs or you can choose to install them individually as
    npm i --save sequelize
    npm i --save passport
    npm i --save passport-local
    npm i --save mysql2
    npm i --save mysql
    npm i --save express
    npm i --save express-session
    npm i --save body-parser
    npm i --save bcryptjs

Adding --save makes sure your dependency is added and saved to your package.json file. This is important if you want to deploy this app. You will realize a new folder called node_modules. Do not touch this. This is what node uses to run the app locally on your computer. If you are using Git for your project do not forget to add node_modules to your .gitignore file in your project's root folder.

Thanks to the contribution from Jordan White, I think it is worth to mention that you must have Sequelize CLI installed before you can use sequelize. Do this by running npm install -g sequelize-cli from your preferred terminal to install it globally or you can remove -g to have it installed locally.

  1. Open the server.js file created in your favorite terminal and input a few lines of code in our server.js file. Don't worry, I will have a horse-load of comments on all the codes so it is easy to understand why i wrote each line. You can copy the code below into your server file.
// Requiring necessary npm middleware packages 
var express = require("express");
var bodyParser = require("body-parser");
var session = require("express-session");
// Setting up port
var PORT = process.env.PORT || 8080;
// Creating express app and configuring middleware 
//needed to read through our public folder
var app = express();
app.use(bodyParser.urlencoded({ extended: false })); //For body parser
app.use(bodyParser.json());
app.use(express.static("public"));
//
//we are doing a GET to test if our server is working fine
app.get('/', function(req, res) {    
       res.send('Welcome to Passport with Sequelize and without HandleBars');
});
//
//this will listen to and show all activities on our terminal to 
//let us know what is happening in our app
app.listen(PORT, function() {
    console.log("App listening on PORT " + PORT);
  });

Save the server file. Let us run the server to make sure it is working properly. Do this by typing npm start or node server.js in your terminal. You remember the entry point when we run npm init? This is what is called when you run npm start.

If you followed the instruction well up to this point you should see the following

Open your browser and enter the location localhost:8080. This will display Welcome to Passport with Sequelize and without HandleBars. Great Job!! on getting this far. You are on your way to creating your app. If you don't see that page look up the steps from the beginning. You can end the server and go back to your code.

  1. I assumed from the beginning you might have already created your database. If you have not and or do not know how to go about this do not worry. Just open your MySQL program of choice and from the query shell enter CREATE DATABASE passport_demo; and run it. You should have a database created with name passport_demo.

  2. Now that we have our server and database working it is time to add the other parts. We will configure and initialize our sequelize module. Do this by typing sequelize init:models & sequelize init:config on your terminal and press enter.
    After this code runs, you should see two folders models and config.
    Open the config folder and you should see a config.json file. Open it and edit the development object's settings to match yours. If you have a password on your database enter it here in quotes. Example is below

{
  "development": {
    "username": "root",
    "password": "yourpassword",
    "database": "passport_demo",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}

Navigate back and open the models folder. You should see an index.js file. This should be unchanged for our tutorial but if you have your config folder in a different location you can open it and edit Line 8 from Col 37 to route to your location because it will need the config.json file to work.Some Windows PCs will also throw an error that it couldn't find the config module. change the backslashes on that to forward slashes to fix that error.

  1. In the models folder create a new file called user.js. This is going to insert our user information to the database using sequelize. You can have multiple model files depending on your needs. The models folder should contain the various table inserts that you make in the database.In this tutorial we want a user model. We will require the bcryptjs package to encrypt and decrypt the password that the user creates or logs in with. Your user.js file should look like this
// Requiring bcrypt for password hashing. Using the bcryptjs version as 
//the regular bcrypt module sometimes causes errors on Windows machines
var bcrypt = require("bcryptjs");
//
// Creating our User model
//Set it as export because we will need it required on the server
module.exports = function(sequelize, DataTypes) {
  var User = sequelize.define("User", {
    // The email cannot be null, and must be a proper email before creation
    email: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
      validate: {
        isEmail: true
      }
    },
    // The password cannot be null
    password: {
      type: DataTypes.STRING,
      allowNull: false
    }
  });
  // Creating a custom method for our User model. 
  //This will check if an unhashed password entered by the 
  //user can be compared to the hashed password stored in our database
  User.prototype.validPassword = function(password) {
    return bcrypt.compareSync(password, this.password);
  };
  // Hooks are automatic methods that run during various phases of the User Model lifecycle
  // In this case, before a User is created, we will automatically hash their password

  User.hook("beforeCreate", function(user) {
    user.password = bcrypt.hashSync(user.password, bcrypt.genSaltSync(10), null);
  });
  return User;
};

//This is a fix by Samaila Philemon Bala in case you want to use ES6
//and the above is not working

//User.beforeCreate(user => {
  //  user.password = bcrypt.hashSync(
    //  user.password,
      //bcrypt.genSaltSync(10),
      //null
    //);
  //});
  1. Let us go back to our server.js file and add a few lines of code. We will need to require the server to read the models folder and we will also need it to sync our inserts and reads to the database. Your server.js should look like this
// Requiring necessary npm middleware packages 
var express = require("express");
var bodyParser = require("body-parser");
var session = require("express-session");
// Setting up port
var PORT = process.env.PORT || 8080;
//Import the models folder
var db = require("./models");
//
// Creating express app and configuring middleware 
//needed to read through our public folder
var app = express();
app.use(bodyParser.urlencoded({ extended: false })); //For body parser
app.use(bodyParser.json());
app.use(express.static("public"));
//
//we are doing a GET to test if our server is working fine
app.get('/', function(req, res) {    
       res.send('Welcome to Passport with Sequelize and without HandleBars');
});
//
//this will listen to and show all activities on our terminal to 
//let us know what is happening in our app
// Syncing our database and logging a message to the user upon success
db.sequelize.sync().then(function() {
  app.listen(PORT, function() {
    console.log("==> 🌎  Listening on port %s. Visit http://localhost:%s/ in your browser.", PORT, PORT);
  });
});
  1. Now let us navigate to the config folder and create another folder called middleware and inside that folder create a file called isAuthenticated.js. You should have /config/middleware/isAuthenticated.js. Open and edit the isAuthenticated.js file to match this
// This is middleware for restricting routes a user is not allowed to visit if not logged in
module.exports = function(req, res, next) {
  // If the user is logged in, continue with the request to the restricted route
  if (req.user) {
    return next();
  }
  // If the user isn't' logged in, redirect them to the login page
  return res.redirect("/");
};

This will be exported also and we will need this to restrict access to pages meant for logged in users only.

  1. It is time to set up passport. In the config folder create a file called passport.js. Open the file and input the following in the file. The comments explain it all.
//we import passport packages required for authentication
var passport = require("passport");
var LocalStrategy = require("passport-local").Strategy;
//
//We will need the models folder to check passport agains
var db = require("../models");
//
// Telling passport we want to use a Local Strategy. In other words,
//we want login with a username/email and password
passport.use(new LocalStrategy(
  // Our user will sign in using an email, rather than a "username"
  {
    usernameField: "email"
  },
  function(email, password, done) {
    // When a user tries to sign in this code runs
    db.User.findOne({
      where: {
        email: email
      }
    }).then(function(dbUser) {
      // If there's no user with the given email
      if (!dbUser) {
        return done(null, false, {
          message: "Incorrect email."
        });
      }
      // If there is a user with the given email, but the password the user gives us is incorrect
      else if (!dbUser.validPassword(password)) {
        return done(null, false, {
          message: "Incorrect password."
        });
      }
      // If none of the above, return the user
      return done(null, dbUser);
    });
  }
));
//
// In order to help keep authentication state across HTTP requests,
// Sequelize needs to serialize and deserialize the user
// Just consider this part boilerplate needed to make it all work
passport.serializeUser(function(user, cb) {
  cb(null, user);
});
//
passport.deserializeUser(function(obj, cb) {
  cb(null, obj);
});
//
// Exporting our configured passport
module.exports = passport;
  1. For our app to work as expected we need to be able to GET and POST to our database. Example of this is the app.get code block we placed in the server.js file. Let us write a clean code. Create a folder in your root folder called routes and also create two files called api-routes.js and html-routes.js. The api-routes.js will be used to route GET and POST from and to the database. open the api-routes.js and paste the following. The comments explain it all.
// Requiring our models and passport as we've configured it
var db = require("../models");
var passport = require("../config/passport");
//
module.exports = function(app) {
  // Using the passport.authenticate middleware with our local strategy.
  // If the user has valid login credentials, send them to the members page.
  // Otherwise the user will be sent an error
  app.post("/api/login", passport.authenticate("local"), function(req, res) {
    // Since we're doing a POST with javascript, we can't actually redirect that post into a GET request
    // So we're sending the user back the route to the members page because the redirect will happen on the front end
    // They won't get this or even be able to access this page if they aren't authed
    res.json("/members");
  });
//
  // Route for signing up a user. The user's password is automatically hashed and stored securely thanks to
  // how we configured our Sequelize User Model. If the user is created successfully, proceed to log the user in,
  // otherwise send back an error
  app.post("/api/signup", function(req, res) {
    console.log(req.body);
    db.User.create({
      email: req.body.email,
      password: req.body.password
    }).then(function() {
      res.redirect(307, "/api/login");
    }).catch(function(err) {
      console.log(err);
      res.json(err);
      // res.status(422).json(err.errors[0].message);
    });
  });
//
  // Route for logging user out
  app.get("/logout", function(req, res) {
    req.logout();
    res.redirect("/");
  });
//
  // Route for getting some data about our user to be used client side
  app.get("/api/user_data", function(req, res) {
    if (!req.user) {
      // The user is not logged in, send back an empty object
      res.json({});
    }
    else {
      // Otherwise send back the user's email and id
      // Sending back a password, even a hashed password, isn't a good idea
      res.json({
        email: req.user.email,
        id: req.user.id
      });
    }
  });
};

Let us leave the html-routes.js for now. We will come back to it. We will need it to handle login and serve our pages.

  1. On the server.js file we will need to import and initialize passport. Make sure your express is initialized before passport as passport requires express. The markup in the server is very important. I will also remove the app.get code block since we don't need it. Your server file should look like the below
// Requiring necessary npm packages
var express = require("express");
var bodyParser = require("body-parser");
var session = require("express-session");
// Requiring passport as we've configured it
var passport = require("./config/passport");
//
// Setting up port and requiring models for syncing
var PORT = process.env.PORT || 8080;
var db = require("./models");
//
// Creating express app and configuring middleware needed for authentication
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static("public"));
// We need to use sessions to keep track of our user's login status
app.use(session({ secret: "keyboard cat", resave: true, saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
//
// Requiring our routes
require("./routes/html-routes.js")(app);
require("./routes/api-routes.js")(app);
//
// Syncing our database and logging a message to the user upon success
db.sequelize.sync().then(function() {
  app.listen(PORT, function() {
    console.log("==> 🌎  Listening on port %s. Visit http://localhost:%s/ in your browser.", PORT, PORT);
  });
});

Note that we are requiring html-routes also. The Next step is to create our user interface (UI) to be able to capture the user's information for signing in and or logging in. This will be the regular html files we usually create with its css and js files but this time it will be placed in a public folder. This is the folder express will use and parse from. If you are conversant with POSTMAN you can test the server using it at this point.

  1. I created a sample public folder with its files in it. which is what i will be using for this tutorial. Download it from Mediafire and unzip into the root folder.

  2. Take a look at the html files in the public folder. You will see that I captured the signup, login, and members page GETs using APIs. This way we can pass it to the server with ease.

  3. Now open the html-routes.js and paste the following code

// Requiring path to so we can use relative routes to our HTML files
var path = require("path");
//
// Requiring our custom middleware for checking if a user is logged in
var isAuthenticated = require("../config/middleware/isAuthenticated");
//
module.exports = function(app) {
//
  app.get("/", function(req, res) {
    // If the user already has an account send them to the members page
    if (req.user) {
      res.redirect("/members");
    }
    res.sendFile(path.join(__dirname, "../public/signup.html"));
  });
//
  app.get("/login", function(req, res) {
    // If the user already has an account send them to the members page
    if (req.user) {
      res.redirect("/members");
    }
    res.sendFile(path.join(__dirname, "../public/login.html"));
  });
//
  // Here we've add our isAuthenticated middleware to this route.
  // If a user who is not logged in tries to access this route they will be 
  //redirected to the signup page
  app.get("/members", isAuthenticated, function(req, res) {
    res.sendFile(path.join(__dirname, "../public/members.html"));
  });
};

Save all files and then run the server with npm start or node server.js. If your server fails check the error on your terminal and go over everything from this tutorial. Take a look at */public/js/members.js* and you will be able to understand what you need in order to get the user information. Sequelize automatically creates an id for a user so you can use it to handle associations on other tables in the database.
If for example you are looking to authenticate on a classified website all you will have to make sure is to have a model such as posting to insert into database, api route to do the post, html route to GET page before and after Post to the database. Always make sure you pass isAuthenticated on any html route that you do not want the user to access without logging in. isAuthenticated will always check for access if used.

I hope my very literal explanation is able to help you figure out your authentication without the use of handlebars or MongoDB.

Richard Debrah

Discussion

pic
Editor guide
 

To get the user model to work, I changed the code into the following

module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('User', {
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true
}
},
password: {
type: DataTypes.STRING,
allowNull: false
}
}, {
hooks: {
beforeCreate: function(user) {
user.password = bcrypt.hashSync(user.password, bcrypt.genSaltSync(10), null);
}
}
})

// Creating a custom method for our User model.
//This will check if an unhashed password entered by the
//user can be compared to the hashed password stored in our database
User.prototype.validPassword = function(password) {
return bcrypt.compareSync(password, this.password);
};
// Hooks are automatic methods that run during various phases of the User Model lifecycle
// In this case, before a User is created, we will automatically hash their password
/*
User.hook("beforeCreate", function(user) {
user.password = bcrypt.hashSync(user.password, bcrypt.genSaltSync(10), null);
});
*/
return User;
};

 

I am glad it worked with the update. I will try to figure out your add and incorporate it for others.

 

All long day search similar articles and debugging the code, finally, the code can run.

i changed line 27 of index.js
from
const model = sequelize'import';
db[model.name] = model;
become
const model = (path.join(__dirname, file));
sequelize'import';
db[model.name] = model;

But i still wonder why its can work.

And then I try @lawmaina78 , its work too without changing index.js

Note: I newbie, this is my second-day doing nodejs before I'm C# Programmer.

Thanks, Ricard Debrah for the awesome article.

 

Great tutorial I was able to recreate most of it on my own web app but I am getting this error when I try to setup a new account-
Executing (default): SELECT id, FirstName, LastName, Username, Email, Password, createdAt, updatedAt FROM Users AS User WHERE User.email = 'test@test.com' LIMIT 1;
Unhandled rejection Incorrect arguments

 

@cristiano thank you for taking time to read this article. Can you kindly send all the error output so i can help?
unhandled rejection error from sequelize can be from any number of reasons with respect to the model. make sure you are passing the right associations as it is checked against your model when you make a select/read from the db

 

Sure! I only get that error when setting up a new account but it actually inserts the data into the database so i moved on from it.
Now when I try to login using the credentials I used when I first set up an account, I get a Cannot Get /[object %20Response]

I've switched up the code a little so I'll show you what mine looks like. I have an ejs file with a link to the script and a button that calls the submit function :


<script type="text/javascript" src="/scripts/login.js"></script>
<button type="button" onclick="submit()" class="btn">Sign in</button>

Then the login.js looks like this:


``` function submit() {

var emailInput = document.getElementById("email").value;
var passwordInput =document.getElementById("password").value;

var userData = {
email: emailInput.trim(),
password: passwordInput.trim()
};

if (!userData.email || !userData.password) {
return;
}

// If we have an email and password we run the loginUser function and clear the form
loginUser(userData.email, userData.password);
emailInput.val("");
passwordInput.val("");
};

// loginUser does a post to our "APIlogin" route and if successful, redirects us the the members page
function loginUser(email, password) {
fetch("/APIlogin", {
method: 'POST',
email: email,
password: password
}).then(function(data) {
window.location.replace(data);
// If there's an error, log the error
}).catch(function(err) {
console.log(err);
});
}```

and then finally the app.js and APIlogin call looks like this respectively:


app.post('/APIlogin', passport.authenticate("local"), APIlogin);

and


APIlogin:(req, res)=> {
res.json("/questions");
}

 

I believe this is meant for you, @cristianooo ? Looks interesting though. 😃

 

Thank you soo much man. I encountered a lil problem with User.hooks but it's all good now

change
User.hook("beforeCreate", function(user) {
user.password = bcrypt.hashSync(user.password, bcrypt.genSaltSync(10), null);
});

to

User.beforeCreate(function (user, options) {
user.password = bcrypt.hashSync(user.password, bcrypt.genSaltSync(10), null);
});

 

Hey Richard,

Thank you for making an effort to solve the issue, I agree they are various tutorials for MongoDB, EJS, Php, etc.. for the login registration with passport but yours is the only one that I could find with MySQL and HTML. Perfect for what I was looking for.

I need your help for an error,
db[model.name] = model;
^

TypeError: Cannot read property 'name' of undefined

this error is in the index.js file.

Looking forward to your reply.

 

Great Tutorial!
Everything works fine but I have a question. How can I use Auth and return a token using passport?
I'm tying to access with Nebular Auth:
akveo.github.io/nebular/docs/auth/...

 

TypeError: dbUser.validPassword is not a function
at E:\pocnode\src\controllers\admin\auth\passport.js:39:26
at runCallback (timers.js:705:18)
at tryOnImmediate (timers.js:676:5)
at processImmediate (timers.js:658:5)
From previous event:
at E:\pocnode\src\controllers\admin\auth\passport.js:33:53
at process._tickCallback (internal/process/next_tick.js:61:11)

Below i have mention the code

'use strict';
var bcrypt = require('bcrypt-nodejs');
module.exports = (sequelize, DataTypes) => {
var user = sequelize.define('user', {
email: DataTypes.STRING,
password: DataTypes.STRING,
status: DataTypes.INTEGER
}, {});
user.associate = function(models) {
// associations can be defined here
};

user.prototype.validPassword = function (password) {
return bcrypt.compareSync(password, this.password);
};

/* generateHash(password) {
return bcrypt.hash(password, bcrypt.genSaltSync(8));
},
validPassword(password) {
return bcrypt.compare(password, this.password);
}*/
return user;
};

 

I am getting this error in my code please help me to solve this issue.

This model code.
'use strict';
var bcrypt = require('bcrypt-nodejs');
module.exports = (sequelize, DataTypes) => {
var user = sequelize.define('user', {
email: DataTypes.STRING,
password: DataTypes.STRING,
status: DataTypes.INTEGER
}, {});
user.associate = function(models) {
// associations can be defined here
};

user.prototype.validPassword = function (password) {
return bcrypt.compareSync(password, this.password);
};

/* generateHash(password) {
return bcrypt.hash(password, bcrypt.genSaltSync(8));
},
validPassword(password) {
return bcrypt.compare(password, this.password);
}*/
return user;
};

Passport.js code.
var User = require('../../../models/').user;

const LocalStrategy = require('passport-local').Strategy;
var bcrypt = require('bcrypt-nodejs');

module.exports = function (passport) {

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

// used to deserialize the user
passport.deserializeUser(function (id, done) {
     User.findById(id).then(function(user) {
          return done(null, user);
    }).catch(function (err) {
    return done(err),null;
    });

});

passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true // allows us to pass in the req from our route (lets us check if a user is logged in or not)
},
function (req, email, password, done) {
if (email)
// asynchronous
process.nextTick(function () {
User.findAll({where: {email: email,status: 1}}).then( function (user) {
if (!user && user.length==0){
return done(null, false , req.flash('message','All fields are required.'));
}else if (!User.validPassword(password)) {
return done(null, false, req.flash('message','Invalid username or password.'));
}
return done(null, user);
})
.catch(function (error) {
return done(error);
});
});

    }));

};

 

Thank you very much for help. The article is clear to understand.

I am getting this error:
\learningPassportJS\models\index.js:31
db[model.name] = model;
^
TypeError: Cannot read property 'name' of undefined

Not sure what I'm missing :(

 

I got the same error. It took several hours to troubleshoot. The below code worked for me. However, it requires adding "return User" in your js file that contains the User object. In my case, it's in my user.js file.

So, my index.js file code snippet looks like this:

.forEach((file) => {
const model = sequelize.import(path.join(__dirname, file))
console.log("model " + model)
try {
db[model.name] = model
console.log("working")
} catch (err) {
console.error(err)
}

My user.js file contains this important line of code:

return User;
 

Great article man

there is a small typo

..... Handlebars as the ORM and MondoDB as the DBMS which at that time, i was not that .....

You wrote MondoDB instead of mongo db

 

Thank you Joshy. You are right. I will fix it.

 

Hi there,
anyone getting this?

Cannot GET /[object%20Object]

 

FIX:
bcrypt-nodejs is no longer supported. npmjs.com/package/bcrypt-nodejs
make sure do get the latest version via npm called bcrypt or bcryptjs.

In user.js just change

var bcrypt = require("bcrypt-nodejs");

to

var bcrypt = require("bcryptjs");

 

Error: Can't set headers after they are sent.
Did someone got same problem?

 

Very detailed , thanks for the same.. am using this to try out nodejs.. will keep this forum updated on how this goes :)

 

i get this error with your code how do i fix this?

models/users.js:36
User.hook("beforeCreate", function(user) {
TypeError: User.hook is not a function

 

Hi @anunes . Thank you for taking time to read the article. Can you kindly (if possible) push your work to github and share with me? that will be easy for me to debug what is happening.

But User.hook not being a function basically means you are calling the hook on the wrong model or instance of User. Kindly check your code to make sure you are passing User as the model as your hook is supposed to be bound to it.

 

Do you have the code of this app somewhere in Github so I can clone directly from there and study. I am also getting User.hook not a function error.

 

How did you solve this, am getting a similar error

 

I think sequelize modified their doc. I had to do this

Users.beforeCreate(user => {
    user.password = bcrypt.hashSync(
      user.password,
      bcrypt.genSaltSync(10),
      null
    );
  });

before it worked. Check out the doc Hooks

Can we use this authentication for Electron Desktop App too?

I have no idea as I haven't used Electron