Why is my Express api register route not POSTing? - javascript

I am trying to make a small authentication system for a practice project I have. I am trying to send POST requests via postman to my express server(http://localhost:4000/api/register), and it's replying back "404 not found" I am following the tutorial here.
Here is my server.js:
const newpost = require('./routes/newpost');
const getposts = require('./routes/getposts');
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const deleteposts = require('./routes/delete');
const editposts = require('./routes/editposts');
const path = require('path');
const app = express();
const webpack = require('webpack');
const webpackConfig = require('../webpack.config');
const webpackMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const passport = require('passport');
const port = 4000;
const compiler = webpack(webpackConfig);
const config = require('./config/main');
const mongoose = require('mongoose');
const authRouter = require('./routes/authrouter');
const logger = require('morgan');
// db connection
mongoose.connect(config.database);
app.use(passport.initialize());
/*
app.use(webpackMiddleware(compiler, {
noInfo: true, publicPath: webpackConfig.output.publicPath,
}));
app.use(webpackHotMiddleware(compiler, {
log: console.log,
}));
*/
app.use(cors());
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
app.use(logger('dev'));
app.use('/newpost', newpost);
app.use('/posts', getposts);
app.use('/delete', deleteposts);
app.use('/edit', editposts);
//auth router to handle auth routes
authRouter(app);
/*
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, '../public/index.html'));
}); */
app.listen(port, () => {
console.log(`Listening on port ${port}`);
});
Here is my authrouter.js. These are the routes I'm exporting into my server.js. :
const AuthenticationController = require('../controllers/authentication');
const express = require('express');
// const passportService = require('../config/passport');
/* eslint-disable */
const passport = require('passport');
// Middleware to require login/auth
// const requireAuth = passport.authenticate('jwt', { session: false });
const requireLogin = passport.authenticate('local', { session: false });
module.exports = function(app){
"use-strict";
// init route groups
const apiRoutes = express.Router();
const authRoutes = express.Router();
// auth routes
// set auth routes as subgroup/middleware to apiRoutes
apiRoutes.use('/auth', authRoutes);
// Registration routes
authRoutes.post('/register', AuthenticationController.register);
// Login route
authRoutes.post('/login', requireLogin, AuthenticationController.login);
// Set url for API group routes
app.use('/api', apiRoutes);
};
Here is my authentication.js
const jwt = require('jsonwebtoken');
// const crypto = require('crypto'); used for pw resets
const User = require('../models/user');
const config = require('../config/main');
function generateToken(user) {
return jwt.sign(user, config.secret, {
expiresIn: 10080, // in seconds
});
}
// set user info from request
function setUserInfo(request) {
return {
_id: request._id,
email: request.email,
role: request.role,
};
}
// Login Route
exports.login = function (req, res, next) {
const userInfo = setUserInfo(req.user);
res.status(200).json({
token: `JWT${generateToken(userInfo)}`,
user: userinfo,
});
};
// registration route
exports.register = function (req, res, next) {
// check for registration errors
const email = req.body.email;
const password = req.body.password;
// Return error if no email provided
if (!email) {
return res.status(422).send({ error: 'You must enter an email address' });
}
// Return error if no pw provided
if (!password) {
return res.status(422).send({ error: 'You must enter a password' });
}
User.findOne({ email }, (err, existingUser) => {
if (err) { return next(err); }
// if user is not unique, return error
if (existingUser) {
return res.status(422).send({ error: 'That email address is already in use' });
}
// if email is unique and pw was provided, create acct
const user = new User({
email,
password,
});
user.save((err, user) => {
if (err) { return next(err); }
// Subscribe member to Mailchimp list
// mailchimp.subscribeToNewsLetter(user.email);
// Respond with JWT if user was created
const userInfo = setUserInfo(user);
res.status(201).json({
token: `JWT ${generateToken(userInfo)}`,
user: userInfo,
});
});
});
};
// Role authorization check
exports.roleAuthorization = function (role) {
return function (req, res, next) {
const user = req.user;
User.findById(user._id, (err, foundUser) => {
if (err) {
res.status(422).json({ error: 'No user was found' });
return next(err);
}
// if user is found, check role
if (foundUser.role == role) {
return next();
}
res.status(401).json({ error: 'You are not authorized to view this content ' });
return next('Unauthorized');
});
};
};
Here is my passport.js :
// Importing Passport; strategies; and config
const passport = require('passport');
const User = require('../models/user');
const config = require('./main');
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const LocalStrategy = require('passport-local');
const localOptions = { usernameField: 'email' };
// setting up the local Strategy
const localLogin = new LocalStrategy(localOptions, ((email, password, done) => {
User.findOne({ email }, (err, user) => {
if (err) { return done(err); }
if (!user) {
return done(null, false, { error: 'Your login details could not be verified. Please try again.',
});
}
user.comparePassword(password, (err, isMatch) => {
if (err) { return done(err); }
if (!isMatch) {
return done(null, false, { error: 'Your login details could not be verified. Please try again.',
});
}
return done(null, user);
});
});
}));
const jwtOptions = {
// Telling passport to check auth headers for JWT
jwtFromRequest: ExtractJwt.fromAuthHeader(),
// Telling passport where to find the secret
secretOrKey: config.secret,
};
// setting up JWT login strategy
const jwtLogin = new JwtStrategy(jwtOptions, ((payload, done) => {
User.findById(payload._id, (err, user) => {
if (err) { return done(err, false); }
if (user) {
done(null, user);
} else {
done(null, false);
}
});
}));
// allow passport to use the strategies we defined
passport.use(jwtLogin);
passport.use(localLogin);

I believe the correct post endpoint would be api/auth/register

Related

I don't want to login if I already login in node js

Everything is going great which I shared code but the problem is that when I log in the next time when I visit the website it shows me again the login form so I don't want this process repeatedly
I used there bcrypt,jwt token and cookies for user login
This is my route where I define user register and login
router.post("/api/usersave", urlencodedParser, vUserController.createUser)
router.post("/api/userlogin", urlencodedParser, vUserController.loginUser)
This is my controller of user registration and login
const express = require("express");
const app = express();
const path = require("path")
var bodyParser = require('body-parser')
const mongoose = require("mongoose")
const hbs = require('hbs');
const router = express.Router()
const bcrypt = require("bcrypt")
const jwt = require("jsonwebtoken")
const cookieparser = require("cookie-parser")
exports.createUser=(req, res)=>{
// console.log(req.body.itemname)
const oldUser = userModel.findOne({ username: req.body.username });
if (oldUser) {
return res.status(409).send("User Already Exist. Please Login");
}
const rsUsers = new userModel(req.body)
rsUsers.save().then(() => {
console.log('User: ' + req.body.username + ' Saved')
}).catch((err)=>{
console.log('User Saved Error..' + err)
});
res.render("home", {abc: req.body})
// res.send("User Created ... ")
return true
}
exports.loginUser= async (req, res)=>{
// console.log(req.body.username)
// console.log(password)
var password = req.body.password
const findUser = await userModel.findOne({username: req.body.username})
// console.log(findUser.username)
if (!findUser){
res.send("User ID Not Found")
}
else {
bcrypt.compare(req.body.password, findUser.password, function(err, result) {
if (!result){
// console.log('User Login Failed')
res.send("User Login Failed")
}
else{
console.log('User Login Successfully')
const vToken = findUser.generateJWTToken()
res.cookie("node1", vToken)
// console.log(vToken)
res.render("home", {abc: req.body})
}
});
}
}
This is my model of user registration and login
const express = require("express");
const app = express();
const path = require("path")
var bodyParser = require('body-parser')
const mongoose = require("mongoose")
const bcrypt = require('bcrypt')
const jwt = require("jsonwebtoken")
const schema2 = new mongoose.Schema({
username: {type: String, required: true},
useremail: String,
password: String,
tokens: [{
token: String
}]
})
schema2.pre('save', async function(next){
// var saltrange = bcrypt.genSalt(10)
if(this.isModified("password")){
var saltrange = 10
this.password = bcrypt.hashSync(this.password, saltrange)
next()
}
})
schema2.methods.generateJWTToken = function(){
try {
var generatedtoken = jwt.sign({id: this._id}, "FULLSTACKWEBDEVELOPMENTMEANMERNBATCH")
// console.log(generatedtoken)
this.tokens = this.tokens.concat({token: generatedtoken})
this.save()
return generatedtoken
}
catch(err){
console.log(err)
return "false"
}
}
const userModel = mongoose.model('userModel', schema2)
module.exports = userModel
enter code here
You can control this login page rendering by checking you are valid login user or not. You can check this by a middleware function in your route file
const {isLoggedIn} = require("./middleware");
app.get("/login", isLoggedIn, (req, res)=>{
res.render("login");
})
app.get("/reg", isLoggedIn, (req, res)=>{
res.render("userRegister");
})
//For Logout from this session simply hit logout url
router.get('/logout', async (req, res) => {
res.clearCookie('node1')
res.redirect("/login");
});
where isLoggedIn is a middleware function which will check if you are an existing valid user or not
middleware.js
const jwt = require('jsonwebtoken');
module.exports.isLoggedIn = async(req,res, next)=>{
try{
const token = req.cookies ? req.cookies.node1 : null;
const decoded = token ? jwt.verify(token, "FULLSTACKWEBDEVELOPMENTMEANMERNBATCH") : null
if(decoded){
return res.redirect('/home');
}
console.log(decoded);
next();
}catch(err){
res.render("login");
}
}
Hoping this may work in your case

Node.js, Express: next is not defined,

I am getting Error: next is not defined. I don't know in which file I am getting this error.
Code:
server.js
require("dotenv").config({
path: "C:/Users/dogra/Documents/Web Development/Portfolio/FullStack/AdvanceAuth/.env",
});
const express = require("express");
const connectDB = require("./config/db");
const errorHandler = require("./middleware/errorHandler");
connectDB();
const app = express();
app.use(express.json());
app.use("/api/auth", require("./routes/authRoutes"));
app.use("/api/private", require("./routes/privateRoutes"));
app.use(errorHandler);
const PORT = process.env.PORT || 5000;
const server = app.listen(PORT, () => {
console.log(`Server running on PORT: ${PORT}`);
});
process.on("unhandledRejection", (err, promise) => {
console.log(`Logged Error: ${err.message}`);
server.close(() => process.exit(1));
});
controllers
authController.js
const User = require("../models/userModel");
const ErrorResponse = require("../utils/errorResponse");
exports.register = async (req, res, next) => {
const { username, email, password } = req.body;
try {
const user = await User.create({
username,
email,
password,
});
sendToken(user, 201, res);
} catch (error) {
next(error);
}
};
exports.login = async (req, res, next) => {
const { email, password } = req.body;
if (!email || !password) {
return next(new ErrorResponse("Please enter credentials properly", 400));
}
try {
const user = await User.findOne({ email }).select("+password");
if (!user) {
return next(new ErrorResponse("Email not registered", 401));
}
const isMatch = await user.matchPasswords(password);
if (!isMatch) {
return next(new ErrorResponse("Invalid Password", 401));
}
sendToken(user, 200, res);
} catch (error) {
next();
}
};
exports.forgotPassword = (req, res, next) => {
res.send("ForgotPassword Route");
};
exports.resetPassword = (req, res, next) => {
res.send("ResetPassword Route");
};
const sendToken = (user, statusCode, res) => {
const token = user.getSignedJwtToken();
res.status(statusCode).json({ success: true, token });
};
privateController.js
exports.private = (req, res, next) => {
res.status(200).json({
success: true,
data: "You got access to the private data in this route",
});
};
routes
authRoutes.js
const express = require("express");
const router = express.Router();
// controllers
const {
register,
login,
forgotPassword,
resetPassword,
} = require("../controllers/authControllers");
router.route("/register").post(register);
router.route("/login").post(login);
router.route("/forgotPassword").post(forgotPassword);
router.route("/resetPassword/:resetToken").put(resetPassword);
module.exports = router;
privateRoutes.js
const express = require("express");
const router = express.Router();
const { private } = require("../controllers/privateControllers");
const { protect } = require("../middleware/authMiddleware");
router.route("/").get(protect, private);
module.exports = router;
middlewre
authMiddleware.js
const jwt = require("jsonwebtoken");
const User = require("../models/userModel");
const ErrorResponse = require("../utils/errorResponse");
exports.protect = async (req, res, next) => {
let token;
if (
req.headers.authorization &&
req.headers.authorization.startsWith("Bearer")
) {
token = req.headers.authorization.split(" ")[1];
}
if (!token) {
return next(
new ErrorResponse("Not authorized to access to this route", 401)
);
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findById(decoded.id);
if (!user) {
return next(new ErrorResponse("No User found with this id", 404));
}
req.user = user;
next();
} catch (error) {
return next(new ErrorResponse("Not Authorized to access this route", 401));
}
};
errorHandler.js
const ErrorResponse = require("../utils/errorResponse");
const errorHandler = (err, req, res, next) => {
let error = { ...err };
error.message = err.message;
if (err.code === 11000) {
const message = `Duplicate Field value entered`;
error = new ErrorResponse(message, 400);
}
if (err.name === "ValidationError") {
const message = Object.values(err.errors).map((val) => val.message);
error = new ErrorResponse(message, 400);
}
console.log(error.message);
res.status(error.statusCode || 500).json({
success: false,
error: error.message || "Server Error",
});
};
module.exports = errorHandler;
utils
errorResponse.js
class ErrorResponse extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
}
module.exports = ErrorResponse;
models
userModel.js
const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: [true, "Please enter your username"],
},
email: {
type: String,
required: [true, "Please enter your email"],
unique: true,
lowercase: true,
match: [
/^(([^<>()[\]\\.,;:\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,}))$/,
,
"Please provide a valid email",
],
},
password: {
type: String,
required: [true, "Please enter a valid password"],
minlength: 8,
select: false,
},
resetPasswordToken: String,
resetPasswordExpired: Date,
});
// Hashing Password
UserSchema.pre("save", async function (next) {
if (!this.isModified("password")) {
next();
}
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
});
// Checking if password entered is correct or not
UserSchema.methods.matchPasswords = async function (password) {
return await bcrypt.compare(password, this.password);
};
// Converting user data into JSON WEB TOKEN
UserSchema.methods.getSignedJwtToken = function () {
return jwt.sign({ id: this._id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRE,
});
};
const User = mongoose.model("User", UserSchema);
module.exports = User;
Sorry, for the long question but I really don't know where is the problem. I googled, & found we get next is not defined error when you don't define it source. But, I have defined it inside my all controllers & middleware's.
The problem was in my dotenv path in server.js Since I cloned my project from GitHub in my new laptop the path was different & I forgot to update the path.

Why the user = await User.findOne({ email }) returns null?

I'm setting up a login route and I decided to test it with postman and it worked but later when I was checking my DB configuration I found an error when I fixed the error the login test on postman doesn't work
so in my server.js file I have :
const express = require("express");
const connectDB = require("./config/db");
const app = express();
// Connect to MongoDB
connectDB();
// Initialize middleware
app.use(express.json());
// Define routes
app.use("/api/users", require("./routes/users"));
app.use("/api/auth", require("./routes/auth"));
app.use("/api/posts", require("./routes/posts"));
app.use("/api/profile", require('./routes/profile'));
// Create server
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
The connectDB function in config/db.js :
const mongoose = require("mongoose");
require('dotenv').config()
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
useCreateIndex: true
});
console.log("Successfully connected to MongoDB");
} catch (err) {
console.error(err.message);
}
};
module.exports = connectDB;
In the auth.js route :
const express = require("express");
const router = express.Router();
const { check } = require("express-validator");
const {auth} = require('../middlewares/auth');
const {login} = require('../controllers/authController');
// #route: POST api/auth
// #desc: Login
// #access: Public
router.post("/",
[
check("email", "Email is required").not().isEmpty(),
check("password", "Password is required").not().isEmpty(),
],
login
);
module.exports = router;
The Auth controller in controllers/authController.js :
const { validationResult } = require("express-validator");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
require('dotenv').config()
exports.login = async (req, res) => {
try {
// Check for validation errors
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Check if user exists
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ msg: "Invalid credentials : you must register" });
}
// If exists, check password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ msg: "Invalid credentials : wrong password" });
}
// Return jwt
const payload = {
user: {
id: user.id,
},
};
jwt.sign(payload,
process.env.JWT_SECRET,{expiresIn: 3600},(err, token) => {
if (err) throw err;
res.json({ token });
}
);
} catch (err) {
console.error(err.message);
res.status(500).send("There was an error with the server. Try again later.");
}
}
Everything looks great and when I try to login with postman it returns the "Invalid credentials : you must register" message from this code in authController.js ( when I console.log(user) it returns null ) :
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ msg: "Invalid credentials : you must register" });
}
PS: At first, in the db configuration I forgot to add the mongo client options and everything worked and it returns the token in postman but after fixing the error I had the login problem

isAuthenticated() in Passport js always return false

I have been browsing the forum but I am unable to find the error in my code , it always results in false and I am not able to solve it , Please help me...
Is there any other way to authenticate user instead of passport so that I can use it.I am adding more sentences as it is not allowing me to post my query,Sorry..
const http = require("http"),
hostname = "127.0.0.1",
port = 3000,
bodyParser = require("body-parser"),
mongoose = require("mongoose"),
express = require("express"),
passport = require("passport"),
localStrategy = require("passport-local"),
passportLocalMongoose = require("passport-local-mongoose"),
User = require("./models/user");
app = express();
mongoose.connect("mongodb://localhost/drive", { useNewUrlParser: true });
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(passport.initialize());
app.use(passport.session());
app.use(
require("express-session")({
secret: "Beta tumse na ho payega",
resave: false,
saveUninitialized: false
})
);
passport.use(new localStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(bodyParser.urlencoded({ extended: true }));
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader("Content-Type", "text/plain");
});
app.get("/", function(req, res) {
res.render("index");
});
app.get("/register", function(req, res) {
res.send("hello");
});
app.get("/login", function(req, res) {
res.render("login");
});
app.post(
"/login",
passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login"
}),
function(req, res) {}
);
app.get("/logout", function(req, res) {
req.logout();
res.redirect("/");
});
function isLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
console.log("Not logged");
res.redirect("/login");
}
}
app.get("/secret", isLoggedIn, function(req, res) {
res.send("You are logged in");
});
app.post("/register", function(req, res) {
if (req.body.password === req.body.cpassword) {
User.register(
new User({ username: req.body.username }),
req.body.password,
function(err, user) {
if (err) console.log(err);
else
passport.authenticate("local")(req, res, function() {
res.send("signed up");
});
}
);
} else res.send("Password Mismatch");
});
//DRIVE SCHEMA
//var driveSchema = mongoose.Schema({
// title: String,
// created: { type: Date, default: Date.now }
//});
app.listen(port, hostname, function() {
console.log("Server is running at " + hostname + "/" + port);
});
//./models/user.js file
const mongoose = require("mongoose"),
passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = new mongoose.Schema({
username: String,
password: String
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
I have used passport and jwt library, to authenticate and maintain session for the user. There is no need to maintain user session on server side.
apis/apis.js : This file has all apis end points. /login url will authenticate user using passport and send a token to the client using jwt
const passport = require('passport')
const expRoute = require('express').Router();
let exporter = process.exporter;
expRoute.post('/login', (req, res, next) => {
passport.authenticate(
'local',
{
// successRedirect: '/',
// failureRedirect: '/login',
successFlash: 'Welcome!',
failureFlash: 'Invalid username or password.'
},
(err, user, info) => {
if (err) {
return res.status(500).json(err)
}
else if (user) {
return res.status(200).json({
token: exporter.generateToken(user)
})
}
else {
return res.status(400).json(info)
}
}
)(req, res, next);
})
expRoute.get('/view', exporter.authenticateToken, (req, res) => {
let param = req.finalTokenExtractedData
if (param && exporter.isObjectValid(param, 'tokenId', true, true)) {
let condition = {
_id: param.tokenId
}
let options = {
_id: 0,
password: 0,
__v: 0
}
process.USER.findOne(condition, options) // mongo find
.then((data) => {
res.status(200).json({
result: data,
msg: 'success'
})
})
.catch((mongoErr) => {
exporter.logNow(`USER mongo Error: ${mongoErr}`)
res.status(400).json({
msg: 'user not found'
})
})
}
else {
res.status(404).json({
msg: 'invalid token'
})
}
})
module.exports = expRoute
common/env.js: This file will initialise all connections such mongo, require few files will be used as global
process.CONFIG = require('../configs/config.json')
process.exporter = require("../lib/exporter.js")
process.dbInit = (globalName, mongoUrl, collectionName) => {
require("../models/db-init.js")(mongoUrl, collectionName)
.then((modelObj) => {
process[globalName] = modelObj // will be used as global
})
.catch((dbInitErr) => {
process.exporter.logNow(`dbInit Error: ${dbInitErr}`)
process.exit()
});
}
lib/exporter.js: This file has exporter class which consist of all major functions like mongo connection, authenticateToken, verifyPassword, etc.
const fs = require('fs'),
redis = require("redis"),
path = require("path"),
mongoose = require('mongoose'); mongoose.set('useCreateIndex', true);
const Schema = mongoose.Schema;
var bcrypt = require('bcryptjs')
var jwt = require('jsonwebtoken')
class Exporter {
mongoConnection(mongoURI, schemaObj) {
return new Promise(async (resolve, reject) => {
if (!mongoURI || typeof mongoURI == 'undefined' || mongoURI.length < 1)
return reject('invalid mongo connection url');
return resolve(mongoose.createConnection(mongoURI, { useNewUrlParser: true }))
})
}
createMongoSchema(schemaObj) {
return (new Schema(schemaObj));
}
createMongoModel(mongoDB, collectionName, newSchema) {
if (newSchema)
return mongoDB.model(collectionName, newSchema)
return mongoDB.model(collectionName)
}
authenticateToken(req, res, next) {
const bearerHeader = req.header('authorization')
if (typeof bearerHeader != 'undefined') {
const bearer = bearerHeader.split(' ')
const bearerToken = bearer[1]
jwt.verify(bearerToken, process.CONFIG.jwt.token.activated, (err, data) => {
if (err)
res.status(400).json({
msg: "Invalid token or please try to login again"
})
else {
process.exporter.getSingleHashKeysValuesFromRedis('expired_token', bearerToken)
.then((redisTokendata) => {
if (redisTokendata)
res.status(400).json({
msg: "token expired"
})
else {
req.finalTokenExtractedData = data
// if (req.originalUrl.trim() == process.logoutURL.trim())
req.jwtToken = {
token: bearerToken,
secret: process.CONFIG.jwt.token.activated
}
next()
}
})
.catch((redisTokenError) => {
process.exporter.logNow(`redis token error: ${redisTokenError}`)
res.status(400).json({
msg: "Some went wrong while checking token. Please try later."
})
})
}
})
}
else
res.status(400).json({
msg: "invalid token"
})
}
generateToken(data) {
let expiry = new Date();
// expiry.setDate(expiry.getDate() + 7)
expiry.setMinutes(expiry.getMinutes() + 5)
return jwt.sign({
tokenId: data._id,
exp: parseInt(expiry.getTime() / 1000),
}, process.CONFIG.jwt.token.activated)
}
createPassword(password) {
return new Promise((resolve, reject) => {
if (typeof password == 'undefined' && password == '')
return reject('password empty')
bcrypt.hash(password, 10, async (bErr, hash) => {
if (bErr)
reject(bErr)
else
resolve(hash)
})
})
}
verifyPassword(enteredPassword, savePassword) {
return bcrypt.compareSync(enteredPassword, savePassword)
}
}
module.exports = (new Exporter());
index.js: This is file which you will execute node index.js.
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const passport = require('passport');
require('./common/env')
require('./configs/passport')
const app = express()
const cors = require('cors')
app.use(cors());
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true}))
app.use(passport.initialize())
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
let apis = require('./apis/api')
app.use('/user', apis)
/**
* 404 Handler
*/
app.use((req, res, next)=>{
return res.status(404).send("Endpoint "+req.url +" not found");
})
/**
* if any error or exception occurred then write into a JS file so that app can be restarted
*/
process.on('uncaughtException', (err) => {
console.error(err.stack);
});
app.listen(3000, function(server) {
console.log("App listening at 3000");
});
When index.js file has been executed successfully and listening to a port 3000, then use this URL http://localhost:3000/user/login for authentication, it will accept your username and password, then authenticate using passport and send a token to the client as response. The token can contain user data in encrypted form and have expiry time.
Reference link: https://github.com/arjun-707/login-logout-jwt-nodejs
You need the express-session module.
server.js
// Require a possible config.js file with your configuration variables
const Config = require('./models/config.js');
// If the config module is formed as a class
const config = new Config();
const express = new('express');
const app = express();
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const uuid = require('uuid/v4');
const mongoose = require('mongoose');
// Require your custom passport local strategy file
const passport = require('./models/sessions');
mongoose.connect('mongodb://localhost:27017/your_db_name', {
useNewUrlParser: true
});
// Set the session options
app.use(session({
// Use UUIDs for session IDs
genid: (req) => {
return uuid()
},
// If you want to store the session in MongoDB using mongoose
// Require your personal mon
store: new MongoStore({
mongooseConnection: mongoose.connection
}),
// Define the session secret in env variable or in config file
secret: process.env.SESSION_SECRET || config.sessionSecretKey,
resave: false,
saveUninitialized: true
}));
// Initialize the passport module
app.use(passport.initialize());
// Tell to passport to use session
app.use(passport.session());
./models/session.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt-nodejs');
// Your custom MongoDB connection module
const db = require('./db');
// Configure passport.js to use the local strategy
passport.use(new LocalStrategy({
usernameField: 'username'
},
(username, password, done) => {
db.User.find({
username: username // But it could use email as well
}).then(res => {
const user = JSON.parse(JSON.stringify(res[0]));
if (!user) {
return done(null, false, {
message: 'Invalid credentials.\n'
});
}
if (!bcrypt.compareSync(password, user.password)) {
return done(null, false, {
message: 'Invalid credentials.\n'
});
}
return done(null, user);
}).catch(error => done(error));
}
));
// Tell passport how to serialize the user
passport.serializeUser((user, done) => {
done(null, user._id);
});
// Tell passport how to deserialize the user
passport.deserializeUser((id, done) => {
db.User.find({
_id: id
}).then(res => {
const response = typeof res !== undefined && res.length != 0 ? JSON.parse(JSON.stringify(res[0])) : null;
done(null, response)
}).catch(error => done(error, false))
});
// Export passport for external usage
module.exports = passport;
./models/db.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const uuid = require('uuid/v4');
// Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/your_db_name', {
useNewUrlParser: true
});
// Define the models container
let models = {};
// Prepare your user schema
const userSchema = Schema({
username: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
// Assign the user schema
models.User = mongoose.model('User', userSchema);
// Export for external usage
module.exports = models;
/*
In that way you can wrap in "models" all schemas:
const newSchema = Schema({
name: String
});
models.Newschema = mongoose.model('Newschema', newSchema);
module.exports = models;
And use it externally like:
const db = require('./models/db');
db.User.find({}).then(docs => {}).catch(err => {});
db.Newschema.find({}).then(docs => {}).catch(err => {});
Etc....
*/
./models/config.js
class Config {
constructor() {
this.sessionSecretKey = "my-awesome-secretkey";
/* And other configurations */
}
}
module.exports = Config;
/*
Externally use like:
const Config = require('./models/config');
const config = new Config();
let sessionSecretKey = config.sessionSecretKey;
*/
Then you can use the req.isAuthenticated() after the login:
// POST the username and password to '/login' router
app.post('/login', (req, res, next) => {
passport.authenticate('local', (err, user, info) => {
if (info) {
return res.send(info.message)
}
if (err) {
return next(err);
}
if (!user) {
return res.sendStatus(404); // Is a shortcut
// OR -> res.status(404).end();
// OR -> res.status(404).send('Not found'); as you like
}
req.login(user, (err) => {
if (err) return next(err);
// Store the user object retrieved from MongoDB in `req.session`
req.session.user = user;
return res.sendStatus(200); // Is a shortcut
// OR -> res.status(200).end();
// OR -> res.status(200).send('OK'); as you like
})
})(req, res, next);
});
// The logout logic
app.get('/logout', verifySession, function (req, res) {
req.session.destroy(function (err) {
req.logout();
res.redirect('/');
});
});
// Verify the session to protect private routers
function verifySession(req, res, next) {
if (req.isAuthenticated()) {
next();
} else {
// Forbidden
res.redirect('/');
// OR -> res.sendStatus(403);
// OR -> res.status(403).end();
// OR -> res.status(403).send('Forbidden'); as you like
}
}
Of course you have to run npm install with all the dependencies required defined in package.json file or manually instal with npm i express-session#latest --s for all the dependencies required: npm i module-name#latest --s.
Don't forget the
const server = app.listen(config.port || 3000, () => {
console.log(`Server running on ${server.address().port} port.`);
});
At the end of server.js file. I hope that it will be useful for you.

Could not get any response nodejs rest api

I am working on a rest api based on this tutorial from Joshmorony, I keep running on error "Could not get any response" while testing on Postman. I have tied consuming the end points on ionic3 project but still running on the same problem. What am I doing wrong that might be leading to this error? I would appreciate your support.
Here is my code.
In the controller folder controllers/authentication.js
const jwt = require('jsonwebtoken');
const bluebird = require('bluebird');
const nodemailer = require('nodemailer');
const User = require('../models/user');
const authConfig = require('../config/auth');
const crypto = bluebird.promisifyAll(require('crypto'));
/**
* Generating JWT tokens
*
*/
function generateToken(user){
return jwt.sign(user, authConfig.secret, {
expiresIn: 10080
});
}
function setUserInfo(request){
return {
_id: request._id,
email: request.email,
role: request.role
};
}
/**
* Local login authentication
*
*/
exports.login = function(req, res, next){
var userInfo = setUserInfo(req.user);
res.status(200).json({
token: 'JWT ' + generateToken(userInfo),
user: userInfo
});
}
/**
* Local registration
*
*/
exports.register = function(req, res, next){
var email = req.body.email;
var password = req.body.password;
var role = req.body.role;
if(!email){
return res.status(422).send({error: 'You must enter an email address'});
}
if(!password){
return res.status(422).send({error: 'You must enter a password'});
}
User.findOne({email: email}, function(err, existingUser){
if(err){
return next(err);
}
if(existingUser){
return res.status(422).send({error: 'That email address is already in use'});
}
var user = new User({
email: email,
password: password,
role: role
});
user.save(function(err, user){
if(err){
return next(err);
}
var userInfo = setUserInfo(user);
res.status(201).json({
token: 'JWT ' + generateToken(userInfo),
user: userInfo
})
});
});
}
/**
* Roles Creation
*
*/
exports.roleAuthorization = function(roles){
return function(req, res, next){
var user = req.user;
User.findById(user._id, function(err, foundUser){
if(err){
res.status(422).json({error: 'No user found.'});
return next(err);
}
if(roles.indexOf(foundUser.role) > -1){
return next();
}
res.status(401).json({error: 'You are not authorized to view this content'});
return next('Unauthorized');
});
}
}
In the model folder model/User.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt-nodejs');
var UserSchema = new mongoose.Schema({
email: {
type: String,
lowercase: true,
unique: true,
required: true
},
password: {
type: String,
required: true
},
role: {
type: String,
enum: ['reader', 'creator', 'editor'],
default: 'reader'
},
passwordResetToken: String,
passwordResetExpires: Date,
profile: {
name: String,
gender: String,
location: String,
picture: String
}
}, {
timestamps: true
});
UserSchema.pre('save', function(next){
var user = this;
var SALT_FACTOR = 5;
if(!user.isModified('password')){
return next();
}
bcrypt.genSalt(SALT_FACTOR, function(err, salt){
if(err){
return next(err);
}
bcrypt.hash(user.password, salt, null, function(err, hash){
if(err){
return next(err);
}
user.password = hash;
next();
});
});
});
UserSchema.methods.comparePassword = function(passwordAttempt, cb){
bcrypt.compare(passwordAttempt, this.password, function(err, isMatch){
if(err){
return cb(err);
} else {
cb(null, isMatch);
}
});
}
module.exports = mongoose.model('User', UserSchema);
Routes routes.js
const AuthenticationController = require('./controllers/authentication'),
TodoController = require('./controllers/todo'),
express = require('express'),
passportService = require('./config/passport'),
passport = require('passport');
const requireAuth = passport.authenticate('jwt', {session: false}),
requireLogin = passport.authenticate('local', {session: false});
module.exports = function(app){
var apiRoutes = express.Router(),
authRoutes = express.Router(),
todoRoutes = express.Router();
// Auth Routes
apiRoutes.use('/auth', authRoutes);
authRoutes.post('/register', AuthenticationController.register);
authRoutes.post('/login', requireLogin, AuthenticationController.login);
authRoutes.post('/forgot', AuthenticationController.postForgot);
authRoutes.post('/reset/:token', AuthenticationController.postReset);
authRoutes.post('/account/profile', requireAuth, AuthenticationController.postUpdateProfile);
authRoutes.post('/account/password', requireAuth, AuthenticationController.postUpdatePassword);
authRoutes.get('/protected', requireAuth, function(req, res){
res.send({ content: 'Success'});
});
// Set up routes
app.use('/api', apiRoutes);
}
and lastly app.js file
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const errorHandler = require('errorhandler');
const chalk = require('chalk');
const logger = require('morgan');
const bodyParser = require('body-parser');
const cors = require('cors');
const dotenv = require('dotenv');
const databaseConfig = require('./app/config/database');
const router = require('./app/routes');
/**
* Load environment variables from .env file, where API keys and passwords are configured.
*/
dotenv.load({ path: '.env' });
/**
* Connect to MongoDB.
*/
mongoose.Promise = global.Promise;
mongoose.createConnection(process.env.MONGODB_URI || process.env.MONGOLAB_URI);
mongoose.connection.on('error', (err) => {
console.error(err);
console.log('%s MongoDB connection error. Please make sure MongoDB is running.', chalk.red('✗'));
process.exit();
});
/**
* Express configuration.
*/
app.set('host', process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0');
app.set('port', process.env.PORT || process.env.OPENSHIFT_NODEJS_PORT || 8080);
/**
* Error Handler.
*/
app.use(errorHandler());
/**
* Start Express server.
*/
app.listen(app.get('port'), () => {
console.log('%s App is running at http://localhost:%d in %s mode', chalk.green('✓'), app.get('port'), app.get('env'));
console.log(' Press CTRL-C to stop\n');
});
app.use(bodyParser.urlencoded({ extended: false })); // Parses urlencoded bodies
app.use(bodyParser.json()); // Send JSON responses
app.use(logger('dev')); // Log requests to API using morgan
app.use(cors());
router(app);
I managed to get the error, when I was ruling the app in the terminal I got this error "DeprecationWarning: open() is deprecated in mongoose >= 4.11.0, use openUri() instead, or set the useMongoClient option if using connect() or createConnection(). See http://mongoosejs.com/docs/connections.html#use-mongo-client", when I try to modify mongoose.connect(process.env.MONGODB_URI || process.env.MONGOLAB_URI); to mongoose.createConnection(process.env.MONGODB_URI || process.env.MONGOLAB_URI); thats when I get that error of "Could not get any response". Just opted to go with the old connect(). Hope this will help someone experiencing the same issue.

Categories

Resources