I'm having issues with the authentication part of my app. I keep getting this "TypeError: Cannot read property 'fromAuthHeaderAsBearerToken' of undefined at Object." whenever I run my server.js file. It stops me from progressing any further.
Here is my passport.js file
const JWTStrategy = require('passport-jwt').Strategy;
const ExtractJWT = require('passport-jwt').ExtractJWT;
const User = require('../dbConnection/database.js');
const keys = require('./keys.js');
const opts = {
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey: keys.secretOrKey,
};
module.exports = passport => {
passport.use(
new JWTStrategy(opts, (jwt_payload, done) => {
User.findOne( {id: jwt_payload.id} ).then(user => {
if (user) {
return done(null, user);
}
return done(null, false);
})
.catch(err => console.log(err));
})
);
};
User Schema
const mysql = require('mysql2');
const Sequelize = require('sequelize');
// Initiate mysql connection
const connOptions = {
host: 'localhost',
user: 'root',
password: 'dummypassword',
database: 'countdown',
dialect: 'mysql'
};
const sequelize = new Sequelize(connOptions);
// Connect sequelize to the database
sequelize.authenticate()
.then(console.log('Connection has been successfully established'))
.catch(err => console.error('Unable to connect to the database: ', err));
// Create user model
const User = sequelize.define('user', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false
},
firstName: {
field: 'first_name',
type: Sequelize.STRING,
allowNull: false
},
lastName: {
field: 'last_name',
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING,
allowNull: false
},
password: {
type: Sequelize.STRING,
allowNull: false
}
}, {
tableName: 'users'
});
module.exports = User;
And also my server.js file
const express = require('express');
const _ = require('lodash');
const bodyParser = require('body-parser');
const cors = require('cors');
const passport = require('passport');
const users = require('./routes/api/users.js');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(__dirname + '/client/public'));
app.use(cors());
// Passport Middleware
app.use(passport.initialize());
// Passport config
require('./config/passport')(passport);
// Routes
app.use('/users', users);
const port = process.env.port || 5000;
app.listen(port, () => {
console.log('Server started on port ' + port);
});
I'm so lost as I literally followed a tutorial that walked this through step by step (https://github.com/rishipr/mern-auth) although it was with MongoDB. I originally didn't use sequelize and thought that might be the issue. So I've refactored it to incorporate sequelize but it didn't solve my issue. Googling didn't help either as no one seems to have this specific issue blocking them from running the server.js file (most people I see are having issues when they make an API call).
Any help is appreciated. Thanks!
The problem is with line number 2 in passport.js file
const ExtractJWT = require('passport-jwt').ExtractJWT;
replace with
consst ExtractJWT= require('passport-jwt').ExtractJwt;
passport-jwt have a ExtractJwt class/method not ExtractJWT. Remember Javascrit is a case sensative language.
Related
I have been trying to solve this ise quite a few days and decided to get community help here.
I have been following the tutorial and here is the problem I face. When I try to get the value of req.user.Firstname in the below code, it threw an error of TypeError: Cannot read properties of undefined (reading 'name'). I am not sure what is going wrong here exactly. Below are the codes from my index.js,app.js file,User.js.
Note: I still render the dashboard page but without the firstName value.
App.js file
const path = require("path");
const express = require("express");
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const morgan = require("morgan");
const exphbs = require("express-handlebars");
const connectDB = require("./config/db");
const passport = require("passport");
const session = require("express-session");
const MongoStore = require("connect-mongo");
const routes = require("./routes/index");
const authent = require("./routes/auth");
const bodyParser = require("body-parser");
const cookieSession = require("cookie-session");
//Loading the config
dotenv.config({ path: "./config/config.env" });
//Passport config
require("./config/passport")(passport);
//Coonecting to DB
connectDB();
const app = express();
app.use(express.json());
// Body parser
app.use(express.urlencoded({ extended: false }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
//Morgan
if (process.env.NODE_ENV === "development") {
app.use(morgan("dev"));
}
//Handlebars
app.engine(".hbs", exphbs.engine({ defaultLayout: "main", extname: ".hbs" }));
app.set("view engine", ".hbs");
//Session middleware
app.use(
session({
secret: "the secret",
resave: false,
saveUninitialized: false,
// cookie: { secure: true },
store: MongoStore.create({ mongoUrl: process.env.MONGO_URI }),
})
);
//Passport middleware
app.use(passport.initialize());
app.use(passport.session());
//Static folder
app.use(express.static(path.join(__dirname, "public")));
//Routes
app.use("/", routes);
app.use("/auth", authent);
const PORT = process.env.PORT || 3000;
app.listen(
PORT,
console.log(
`The server is running IN ${process.env.NODE_ENV} mode, on port ${PORT}`
)
);
Index.js
const express = require("express");
const router = express.Router();
const { ensureAuth, ensureGuest } = require("../middleware/auth");
//Description Login/Landing page
//#route GET /
router.get("/", ensureGuest, function (req, res) {
res.render("login", {
layout: "login",
});
});
//Description Dashboard page
//#route GET /dashboard
router.get("/dashboard", ensureAuth, function (req, res) {
res.render("dashboard", {
name: req.user.firstName,
});
});
module.exports = router;
User model
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
googleId: {
type: String,
// required: true,
},
displayName: {
type: String,
required: true,
},
firstName: {
type: String,
required: true,
},
familyName: {
type: String,
required: true,
},
image: {
type: String,
},
createdAt: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model("User", UserSchema);
Passport.js
const GoogleStrategy = require("passport-google-oauth20").Strategy;
const mongoose = require("mongoose");
const User = require("../models/User");
require("https").globalAgent.options.rejectUnauthorized = false;
module.exports = function (passport) {
passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/callback",
},
async (accessToken, refreshToken, profile, done) => {
console.log(profile);
const newUser = {
googleId: profile.id,
displayName: profile.displayName,
firstName: profile.name.givenName,
familyName: profile.name.familyName,
image: profile.photos[0].value,
};
try {
let user = await User.findOne({ googleId: profile.id });
if (user) {
done(null, user);
} else {
user = await User.create(newUser);
done(null, newUser);
}
} catch (error) {
console.log(error);
}
}
)
);
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (user, done) {
User.findById(user.id, function (error, user) {
done(error, user);
});
});
};
Any ideas what I might have been doing wrong here? Thanks!
I've been stuck on this for two days. I got it working last night, and this morning I updated some stuff and removed some unnecessary code, which ended up not working. The error persists on the passport serialization, "TypeError: Cannot set properties of undefined (setting 'user')"
app.js
const mongoose = require("mongoose"); //Mongo driver
var session = require('express-session');
const passport = require('passport');
const MongoStore = require('connect-mongo');
var express = require("express");
const bodyParser = require('body-parser'); //For parsing post requests
//Route files
const mainRoutes = require("./routes/main");
const authRoutes = require("./routes/auth");
require("./passport")(passport);
//Express setup
var app = express();
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());
mongoose
.connect
....
//Express Session
app.use(session({
resave: true,
saveUninitialized: false,
secret: 'SECRET',
store: new MongoStore({ mongoUrl: process.env.MONGO_URI, ttl: 12 * 60 * 60 * 1000 })
}));
//Passport Middleware
app.use(passport.initialize());
app.use(passport.session());
app.use(mainRoutes);
app.use(authRoutes);
passport.js
const bcrypt = require("bcrypt");
const localStrategy = require("passport-local").Strategy;
const FacebookStrategy = require("passport-facebook").Strategy;
... Twitter, Google ..
const Users = require("./models/userModel");
module.exports = function (passport) {
passport.serializeUser(function(user, done){
done(null, user._id);
});
passport.deserializeUser(function(id, done){
Users.findById(id, function(err, user){
done(err, user);
});
});
//..Not including local or the other strategies as they all lead to the same thing
passport.use(new FacebookStrategy({
clientID: process.env.FACEBOOK_APP_ID,
clientSecret: process.env.FACEBOOK_APP_SECRET,
callbackURL: "http://localhost:3000/auth/facebook/callback",
// passReqToCallback : true, //Tried with both these two commented lines
// profileFields: ['id', 'emails']
},
function (req, accessToken, refreshToken, profile, done) {
console.log(profile);
Users.findOrCreate({ "platform.id": profile.id, "platform.name": profile.provider, "email": profile.emails[0].value }, function (err, user) {
console.log(user);
return done(null, user);
});
}));
};
routes/auth.js
const passport = require('passport');
const router = require("express").Router();
...
router.get('/auth/facebook', passport.authenticate('facebook'));
router.get('/auth/facebook/callback', passport.authenticate('facebook', {
successRedirect : '/',
failureRedirect: '/' })
);
...
userModel.js
const mongoose = require("mongoose");
const findOrCreate = require('mongoose-findorcreate');
const {usernameGen} = require("../utils/functions");
const userSchema = new mongoose.Schema({
platform: {
name: String,
id: String
},
email: {
type: String
},
username: {
type: String,
min: 4,
max: 20,
default: usernameGen
},
password: {
type: String,
min: 6
},
isAvatarImageSet: {
type: Boolean,
default: false
},
avatarImage: {
type: String,
default: ""
},
authLevel: {
type: String,
enum: ["admin", "moderator", "member", "anon"],
default: "anon"
},
});
userSchema.plugin(findOrCreate);
module.exports = mongoose.model("Users", userSchema);
Sorry for dumping out most of the stuff here, but passportjs's documentation has been driving me crazy. Found similar issues from other people, but the solutions were to downgrade passportJS to a REALLY older version, or wrong stuff initializing at the wrong place, or just wrongly serializing the user.
Console logging the user going into passport.serializeUser(), reveals all the user data correctly along with the user's _id.
Any help would be greatly appreciated, and thanks for checking my issue out!
I followed a tutorial and tried to implement some code from this repo https://github.com/ArjunAranetaCodes/MoreCodes-Youtube/tree/master/mern-mysql-login-reg. It takes a user's registration information and stores it in a database.
When I put in http://localhost:5000/users/register in postman I get a Cannot GET /users/register and I don't know why.
I don't know if its a problem with the database or not. I should be able to reach /users/register though shouldn't I?
server.js
const cors = require('cors');
const bodyParser = require('body-parser');
const express = require('express');
const port = process.env.PORT || 5000;
const app = express();
app.use(bodyParser.json());
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }))
const Users = require('./routes/Users');
app.use('/users', Users)
app.listen(port, () => {
console.log('SERVER RUNNING ON PORT: ' + port);
});
database/db.js
const Sequelize = require("sequelize")
const db = {}
const sequelize = new Sequelize("accounts", "root", "password", {
host: "localhost",
dialect: "mysql",
operatorAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db
models/User.js
const Sequelize = require('sequelize')
const db = require('../database/db.js')
module.exports = db.sequelize.define(
'user',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
email: {
type: Sequelize.STRING
},
username: {
type: Sequelize.STRING,
},
password: {
type: Sequelize.STRING,
},
name: {
type: Sequelize.STRING,
},
datetime: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW
}
},
{
timestamps: false
}
)
routes/Users.js
const express = require('express')
const users = express.Router()
const cors = require('cors');
const jwt = require('jsonwebtoken')
const bcrypt = require('bcrypt');
const User = require("../models/User")
users.use(cors());
process.env.SECRET_KEY = 'secret'
users.post('/register', (req, res) => {
const today = new Date().toDateString()
const userData = {
email: req.body.email,
username: req.body.username,
password: req.body.password,
name: req.body.name,
datetime: today
}
User.findOne({
where: {
email: req.body.email
}
})
.then(user => {
if (!user) {
bcrypt.hash(req.body.password, 10, (err, hash) => {
userData.password = hash
User.create(userData)
.then(user => {
res.json({ status: user.email + 'REGISTERED' })
})
.catch(err => {
res.send('ERROR: ' + err)
})
})
} else {
res.json({ error: "USER ALREADY EXISTS" })
}
})
.catch(err => {
res.send('ERROR: ' + err)
})
})
module.exports = users
I want to insert a data into db using sequelize express, the below code is working properly, but I want to create a files like controller, config, routes, models like that and postman tool.. I've tried more but I didn't get proper output.
const Sequelize = require('sequelize');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json({ limit: '100mb' }));
app.use(bodyParser.urlencoded({ extended: true, limit: '100mb',
parameterLimit: 1000000 }));
const sequelize = new Sequelize('ganeshdb', 'root', 'welcome123$',
{
host: 'localhost',
port: 3306,
dialect: 'mysql'
});
const users = sequelize.define('users', {
id: {
primarykey: true,
type: Sequelize.INTEGER,
},
name: Sequelize.STRING,
role: Sequelize.STRING,
email: Sequelize.STRING
});
app.post('/test', function (request, response) {
return users.create({
id: request.body.id,
name: request.body.name,
role: request.body.role,
email: request.body.email
}).then(function (users) {
if (users) {
response.send(users);
} else {
response.status(400).send('Error in insert new record');
}
});
});
app.listen(3001, function () {
console.log('Express server is listening on port 3000');
});
You can do it this way:
https://expressjs.com/en/starter/generator.html
Example:
npm install express-generator -g
express --view=pug myapp
And you can see more https://solidgeargroup.com/clean-architecture-in-nodejs
I want to insert a new data in database using sequelize express, without query. I am trying so hard but I didn't get the output... If my code is wrong, then give me a code for insert a new record in db using sequelize express.
const Sequelize = require('sequelize');
var express = require('express');
var app = express();
var mysql = require('mysql');
//var request=require('request')
const sequelize = new Sequelize('ganeshdb', 'root', 'welcome123$', {
host: 'localhost',
port: 3306,
dialect: 'mysql'
});
var users = sequelize.define('users', {
id: {
primaryKey: true,
type: Sequelize.INTEGER,
},
name: Sequelize.STRING,
role: Sequelize.STRING,
email: Sequelize.STRING
});
app.post('/test', function (request, response) {
return users.create({
name: request.body.name,
role: request.body.role,
email: request.body.email
}).then(function (users) {
if (users) {
response.send(users);
} else {
response.status(400).send('Error in insert new record');
}
});
});
app.listen(3000, function () {
console.log('Express server is listening on port 3000');
});
You should use body-parser
https://www.npmjs.com/package/body-parser
Example use body-parser:
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
})
Example:
const Sequelize = require('sequelize');
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json({ limit: '100mb' }));
app.use(bodyParser.urlencoded({ extended: true, limit: '100mb', parameterLimit: 1000000 }));
const sequelize = new Sequelize('test_01', 'root', 'root', {
host: 'localhost',
port: 3306,
dialect: 'mysql'
});
const users = sequelize.define('users', {
id: {
primaryKey: true,
type: Sequelize.INTEGER,
},
name: Sequelize.STRING,
role: Sequelize.STRING,
email: Sequelize.STRING
});
app.post('/test', function (request, response) {
return await users.create({
id: request.body.id,
name: request.body.name,
role: request.body.role,
email: request.body.email
}).then(function (users) {
if (users) {
response.send(users);
} else {
response.status(400).send('Error in insert new record');
}
});
});
app.listen(3001, function () {
console.log('Express server is listening on port 3000');
});