My issue is that on POST, I'm getting a 'Missing Credentials' error whenever I try and authenticate using 'local' strategy. I initially thought that this was an issue with body-parser, but even after some suggestions about forcing urlencoded: true/false, I'm still not getting any differing results. My console logs are also not returning anything substantial beyond irrelevant req.body's, and I'm really not sure what else to do at this point. I've read about this being a potential issue with specific versions of Express, but I've tried downgrading/upgrading and that hasn't changed anything.
With some breakpoints, it looks like my new localStrategy in PassportConfig.js is never being called, but I'm not entirely sure if that's my error or not? Would really appreciate some pointers here.
app.js
require("./config/config");
require("./models/db");
require("./config/passportConfig");
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const passport = require("passport");
// router
var rtsIndex = require("./routes/index.router");
var app = express();
// middleware config
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
app.use(passport.initialize());
app.use(passport.session());
app.use("/api", rtsIndex);
My PassportConfig.js:
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const mongoose = require("mongoose");
var User = mongoose.model("User");
passport.use(
new LocalStrategy({ usernameField: "email" }, (username, password, done) => {
User.findOne({ email: username }, (err, user) => {
if (err) return done(err);
// if user is unknown
else if (!user)
return done(null, false, {
message: "That email address has not been registered"
});
// or if password is wrong
else if (!user.verifyPassword(password))
return done(null, false, { message: "Wrong password" });
// successful authentication
else return done(null, user);
});
})
);
My controller for a basic user registration/login system:
const mongoose = require("mongoose");
const passport = require("passport");
const _ = require("lodash");
User = require("../models/user.model");
// snipped some registration code for brevity
module.exports.authenticate = (req, res, next) => {
console.log(req.body);
// call for passport authentication
// executed passport.use from passportConfig
passport.authenticate("local", (err, user, info) => {
// Error from passport middleware
if (err) return res.status(400).json(err);
// user is registered if there is a value in 'user'
else if (user) return res.status(200).json({ token: user.generateJwt() });
// user unkown or wrong password
else return res.status(401).json(info);
})(req, res);
};
Edit: Added my user model definitions as well:
const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
var userSchema = new mongoose.Schema({
fullName: {
type: String,
required: "Full name cannot be empty"
},
email: {
type: String,
required: "Email cannot be empty",
unique: true
},
password: {
type: String,
required: "Password cannot be empty",
minlength: [4, "Password must be at least 4 characters long"]
},
// Encryption/Decryption of password
saltSecret: String
});
// Custom validation for email
userSchema.path("email").validate(val => {
emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return emailRegex.test(val);
}, "Invalid email");
// Events
userSchema.pre("save", function(next) {
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(this.password, salt, (err, hash) => {
this.password = hash;
this.saltSecret = salt;
next();
});
});
});
// Methods
userSchema.methods.verifyPassword = function(password) {
// plain password, vs encrypted password,
// called from findOne in passportConfig
return bcrypt.compareSync(password, this.password);
};
userSchema.methods.generateJwt = function() {
return jwt.sign({ _id: this._id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXP
});
};
// Can pass custom name as third paramater
// Modified with a force export for debugging
module.exports = mongoose.model("User", userSchema);
And finally, some basic routing:
const express = require("express");
const router = express.Router();
const ctrlUser = require("../controllers/user.controller");
// foreword all links with api/
router.post("/register", ctrlUser.register);
router.post("/authenticate", ctrlUser.authenticate);
// Export router for middleware so app.js can access it
module.exports = router;
I've tried the following solutions to these questions:
- Passport js local strategy custom callback "Missing credentials"
- passport js missing credentials
- Passport returning "missing credentials" error
- Passportjs local strategy missing credentials error message
With it not being the body-parser issue, I thought it might be a usernameField issue, but that doesn't seem to be the case either.