node.js Express - how to do login sessions? - javascript

I'm working doing a login function with node.js Express and are having trouble with sending the session data so my app.js routes know the user is allowed to enter the various sites.
My first thought was to send it when i approve of the login information and redirect to the frontpage in my Auth.js but i can't figure out how to send it so that my frontpage route can see it and handle it with my checkAuth function.
The other idea i had was using a couple of "set/get" routes as shown in my users.js. But can't figure out how i would further implement that.
I don't know which way would be optimal for this sort of application.
This is the Auth.js which is responsible for the login:
const router = require('express').Router();
const User = require("../models/User.js");
const bcrypt = require('bcrypt');
const saltRounds = 12;
router.post('/login', (req, res) => {
// get request from body
const { username, password } = req.body;
//console.log(req.body);
// ask if this is a username with a password
if (username && password) {
// goes through db to see if username exists
User.query().select('username').where('username', username).then(foundUsername => {
try {
if (foundUsername[0].username == username) {
console.log(foundUsername[0].username);
User.query().select("password").where('username', foundUsername[0].username).then(foundPassword => {
console.log(foundPassword[0].password);
bcrypt.compare(password, foundPassword[0].password).then(result => {
console.log(result)
if (result == true) {
// this is where i want to set the req.session.user_id = true;
// and send it to my /frontpage
return res.redirect("/frontpage");
} else {
return res.status(400).send({ response: "wrong username or password" });
};
});
});
} else {
return res.status(400).send({ response: "wrong username or password" });
};
} catch (error) {
return res.status(400).send({ response: "wrong username or password" });
};
});
};
});
module.exports = router;
This is my app.js which checks the incoming request for req.session.user_id
const express = require('express');
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.static('public'));
app.use(express.json());
// You need to copy the config.template.json file and fill out your own secret
const session = require('express-session');
const config = require('./config/config.json');
app.use(session({
secret: config.sessionSecret,
resave: false,
saveUninitialized: true
}));
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use(limiter);
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 8 // limit each IP to 8 requests per windowMs
});
app.use('/signup', authLimiter);
app.use('/login', authLimiter);
/* Setup Knex with Objection */
const { Model } = require('objection');
const Knex = require('knex');
const knexfile = require('./knexfile.js');
const knex = Knex(knexfile.development);
Model.knex(knex);
app.get("/", (req, res) => {
return res.sendFile(__dirname + "/public/login.html");
});
function checkAuth(req, res, next) {
if (!req.session.user_id) {
res.send('You are not authorized to view this page');
} else {
next();
}
}
app.get("/frontpage", checkAuth, (req, res) => {
console.log(req.body);
return res.sendFile(__dirname + "/public/frontpage.html");
});
const authRoute = require('./routes/auth.js');
const usersRoute = require('./routes/users.js');
app.use(authRoute);
app.use(usersRoute);
const PORT = 3000;
app.listen(PORT, (error) => {
if (error) {
console.log(error);
}
console.log("Server is running on the port", PORT);
})
});
This is my users.js. This is another way i thought of getting and setting my session value:
router.get('/setsessionvalue', (req, res) => {
req.session.user_id = true;
return res.send({ response: "OK" });
});
router.get('/getsessionvalue', (req, res) => {
return res.send({ response: req.session.user_id });
});

Related

Getting error when relocating endpoint's place in Express.js

I try to learn REST API and session based Authenticaion in express.js. But I got really interesting error when try to relocate the endpoints.
After relocating the endpoints I send a request to /me endpoint but I get an error. For instance;
// This code works fine
router.get("/me", sessionChecker, async (req, res, next) => {
const { userId } = req.session.payload;
const user = await UserService.findUserById(userId);
return res.json(user);
});
router.get("/:userId", sessionChecker, async (req, res, next) => {
const { userId } = req.params;
const user = await UserService.findUserById(userId);
return res.json(user);
});
to this;
// This code gives error
router.get("/:userId", sessionChecker, async (req, res, next) => {
const { userId } = req.params;
const user = await UserService.findUserById(userId);
return res.json(user);
});
router.get("/me", sessionChecker, async (req, res, next) => {
const { userId } = req.session.payload;
const user = await UserService.findUserById(userId);
return res.json(user);
});
I'am getting this error;
/Users/Desktop/projects/Curioso/backend/node_modules/mongoose/lib/query.js:4913
const castError = new CastError();
^
CastError: Cast to ObjectId failed for value "me" (type string) at path "_id" for model "User"
at model.Query.exec (/Users/Desktop/projects/Curioso/backend/node_modules/mongoose/lib/query.js:4913:21)
at model.Query.Query.then (/Users/Desktop/projects/Curioso/backend/node_modules/mongoose/lib/query.js:5012:15)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
messageFormat: undefined,
stringValue: '"me"',
kind: 'ObjectId',
value: 'me',
path: '_id',
reason: BSONTypeError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer
I couldn't understand what is the problem or logic of this error. Here is the rest of the code;
index.js
const express = require("express");
const session = require("express-session");
const MongoStore = require("connect-mongo");
const mongoose = require("mongoose");
const authRouter = require("./routes/auth");
const roomsRouter = require("./routes/rooms");
const usersRouter = require("./routes/users");
var cors = require("cors");
require("dot-env");
const app = express();
mongoose
.connect(process.env.MONGODB_URL)
.then(() => {
console.log("Connected to DB");
})
.catch((error) => {
console.log(error);
});
var whitelist = ["http://localhost:3000"];
var corsOptions = {
origin: whitelist,
methods: ["POST", "PUT", "GET", "OPTIONS", "HEAD"],
credentials: true,
};
app.use(cors(corsOptions));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
session({
secret: process.env.SESSION_SECRET_KEY,
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 1000 * 60 * 60 * 24,
secure: process.env.NODE_ENV === "production",
httpOnly: true,
},
store: MongoStore.create({
mongoUrl: process.env.MONGODB_URL,
}),
})
);
app.use("/auth", authRouter);
app.use("/rooms", roomsRouter);
app.use("/users", usersRouter);
app.listen(8000, () => {
console.log(`Example app listening on port 8000`);
});
routes/user.js
const express = require("express");
const { sessionChecker } = require("../middlewares/auth");
const router = express.Router();
const UserService = require("../services/user");
router.get("/", sessionChecker, async (req, res, next) => {
const allUsers = await UserService.getAllUsers();
return res.json(allUsers);
});
router.get("/:userId", sessionChecker, async (req, res, next) => {
const { userId } = req.params;
const user = await UserService.findUserById(userId);
return res.json(user);
});
router.get("/me", sessionChecker, async (req, res, next) => {
const { userId } = req.session.payload;
const user = await UserService.findUserById(userId);
return res.json(user);
});
module.exports = router;
middlewares/auth.js
const { HTTP_ERRORS } = require("../utils/constants");
const sessionChecker = (req, res, next) => {
const userSession = req.session.payload.userId;
if (!userSession) {
return res
.status(HTTP_ERRORS.UNAUTHORIZED.CODE)
.send(HTTP_ERRORS.UNAUTHORIZED.MESSAGE);
}
next();
};
module.exports = { sessionChecker };
Because you are using pattern matching /me will go to the route /:userId. Express follows routes from first defined to last defined to find a matching route, this is why the order matters.
It is the practise to put the pattern matching as the last route so /:userId should be the last route.

How to authenticate socket.io connection in nodejs application

I am working on a chat application where socket is used for bi-directional sharing of messages.
The socket currently works fine but I want to be able to authenticate user before they can have access to the socket connection. I have trying to use passport but it would seem there is something I am not doing right as I get the error No session found.
const createError = require("http-errors");
const express = require("express");
const { join } = require("path");
const logger = require("morgan");
const jwt = require("jsonwebtoken");
const cookieParser = require("cookie-parser");
const session = require("express-session");
const SequelizeStore = require("connect-session-sequelize")(session.Store);
const db = require("./db");
const { User } = require("./db/models");
const passport = require('passport');
// create store for sessions to persist in database
const sessionStore = new SequelizeStore({ db });
const http = require("http");
const db = require("../db");
const onlineUsers = require("../onlineUsers");
const passportSocketIo = require('passport.socketio');
const { json, urlencoded } = express;
const app = express();
app.use(logger("dev"));
app.use(json());
app.use(urlencoded({ extended: false }));
app.use(express.static(join(__dirname, "public")));
app.use(cookieParser());
app.use(session({
genid:(req)=>{
return req.cookies
},
secret: process.env.SESSION_SECRET,
resave: true,
store: sessionStore,
saveUninitialized: true,
}));
app.use(function (req, res, next) {
const token = req.cookies["messenger-token"];
if (token) {
jwt.verify(token, process.env.SESSION_SECRET, (err, decoded) => {
if (err) {
return next();
}
User.findOne({
where: { id: decoded.id },
}).then((user) => {
req.user = user;
return next();
});
});
} else {
return next();
}
});
app.use(passport.initialize());
app.use(passport.session());
const port = normalizePort(process.env.PORT || "3001");
app.set("port", port);
/**
* Create HTTP server.
*/
const server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces, and sync database.
*/
const io = require("socket.io")(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST", "PUT"],
credentials: true
}
});
io.use(
passportSocketIo.authorize({
cookieParser: cookieParser,
key: 'messenger-token',
secret: process.env.SESSION_SECRET,
store: sessionStore,
success: onAuthorizeSuccess,
fail: onAuthorizeFail
})
);
function onAuthorizeSuccess(data, accept) {
console.log('successful connection to socket.io');
accept(null, true);
}
function onAuthorizeFail(data, message, error, accept) {
if (error) throw new Error(message);
console.log('failed connection to socket.io:', message);
accept(null, false);
}
io.on("connection", (socket) => {
// console.log(`USER ${JSON.stringify(socket)}`);
socket.on("go-online", (id) => {
if (!onlineUsers.includes(id)) {
onlineUsers.push(id);
}
// send the user who just went online to everyone else who is already online
socket.broadcast.emit("add-online-user", id);
});
socket.on("new-message", (data) => {
socket.broadcast.emit("new-message", {
message: data.message,
sender: data.sender,
});
});
socket.on("read-message", (data) => {
socket.broadcast.emit("read-message", data);
});
socket.on("read-messages", (data) => {
socket.broadcast.emit("read-messages", data);
});
socket.on("logout", (id) => {
if (onlineUsers.includes(id)) {
userIndex = onlineUsers.indexOf(id);
onlineUsers.splice(userIndex, 1);
socket.broadcast.emit("remove-offline-user", id);
}
});
});
How can I authenticate user with socket. Feel free to suggest other method aside using passport.
I found the same error in Github and it hasn't been resolved yet.
According to the official document (see "Compatibility with Express middleware" section), you can use express middleware in io.use by using wrap.
const wrap = middleware => (socket, next) => middleware(socket.request, {}, next);
The section shows how to use "express-session" module with socket.io. I guess this way is better for you because you already use it.

How to initialize passport (issue with exporting)

I have some issues to initiate passport.
I call the function app.use(passport.initialize()); in the file server.js
In the file auth.controllers.js passport is not detected as initialized
Somebody could explain how to "connect" app.use(passport.initialize()) in the server.js to the file auth.controllers.js ?
here my files :
Server.js
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const helmet = require("helmet");
const morgan = require("morgan");
const networkConfig = require("./config/network.config");
const app = express();
const db = require("./config/models");
db.sequelize.sync();
var corsOptions = {
origin: networkConfig.corsOptions.ORIGIN
};
app.use(helmet());
app.use(cors(corsOptions));
app.use(morgan('combined'));
// parsing sur les requetes en type json
app.use(bodyParser.json());
// parsing des urls encodés
app.use(bodyParser.urlencoded({ extended: true }));
// route de vérification de bon fonctionnement
app.get("/", (req, res) => {
res.json({message: "Bienvenue ici"});
});
require("./routes/user.routes")(app);
require("./routes/oauth2.route")(app);
require("./routes/client.routes")(app);
require("./routes/beer.routes")(app);
const ejs = require('ejs');
const session = require('express-session');
const passport = require('passport');
/*
const beerController = require('./controllers/beer');
const userController = require('./controllers/user');
const authController = require('./controllers/auth');
const oauth2Controller = require('./controllers/oauth2');
const clientController = require('./controllers/client');
*/
// Set view engine to ejs
app.set('view engine', 'ejs');
// Use express session support since OAuth2orize requires it
app.use(session({
secret: 'Super Secret Session Key',
saveUninitialized: true,
resave: true
}));
// Use the passport package in our application
app.use(passport.initialize());
// Start the server
app.listen(3000);
user.routes.js
module.exports = app => {
const users = require("../controllers/user.controllers");
const auths = require("../controllers/auth.controllers")(app);
const router = require("express").Router();
// Create endpoint handlers for /users
router.route('/')
.post(users.create)
.get(auths.isAuthenticated, users.findAll);
app.use('/api/users', router);
};
auth.controllers.js
// Load required packages
var passport = require('passport');
var BasicStrategy = require('passport-http').BasicStrategy;
var BearerStrategy = require('passport-http-bearer').Strategy
const db = require("../config/models");
const User = db.user;
const Client = db.client;
const Token = db.token;
const Op = db.Sequelize.Op;
passport.use(new BasicStrategy( (username, password, done) => {
User.findOne({where: { username: username }})
.then(function (data) {
if (!data) {
return done(null, false, { message: 'user does not exist'});
} else {
var verify = data.verifyPassword(password);
if(verify == true) { console.log("verify true"); return done(null, data, {message: 'authentication succeded'})}
}
})
.catch( (err) => {
console.log("Error reason : "+ err);
return done(null, false, { message: 'Something went wrong with you authentication'});
}
)
}
));
passport.use('client-basic', new BasicStrategy(
function(username, password, callback) {
console.log("CLIENT-BASICCLIENT-BASICCLIENT-BASICCLIENT-BASICCLIENT-BASICCLIENT-BASICCLIENT-BASICCLIENT-BASICCLIENT-BASIC");
Client.findOne({ id: username }, function (err, client) {
if (err) { return callback(err); }
// No client found with that id or bad password
if (!client || client.secret !== password) { return callback(null, false); }
// Success
return callback(null, client);
});
}
));
exports.isAuthenticated = passport.authenticate('basic', { session : false });
exports.isClientAuthenticated = passport.authenticate('client-basic', { session : false });
How could I resolve this problem ?
Regards,

Passport + NodeJs + Express getting "req.user" undefined

I am facing a session problem, Getting req.user undefined after successful passport. authenticate method.
Basically after signUp or login, when I am redirecting, unable to find "user" in request variable.
I have used a hackathon starter which was using mongo, I tried to change things to use Postgres.
Edit -- After following suggestions on Comment
Now signup flow is working fine, but login flow having some problem. Something weird happening, when I am adding a lot of breaking points, It seems to do login intermittently. Update code with comment suggestions
app.js
const express = require('express');
const compression = require('compression');
const session = require('express-session');
const bodyParser = require('body-parser');
const logger = require('morgan');
const chalk = require('chalk');
const errorHandler = require('errorhandler');
const lusca = require('lusca');
const dotenv = require('dotenv');
const flash = require('express-flash');
const path = require('path');
const passport = require('passport');
const expressValidator = require('express-validator');
const expressStatusMonitor = require('express-status-monitor');
const sass = require('node-sass-middleware');
const multer = require('multer');
dotenv.load({ path: '.env.example' });
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const models = require('./models');
const upload = multer({ dest: path.join(__dirname, 'uploads') });
/**
* Load environment variables from .env file, where API keys and passwords are configured.
*/
/**
* Controllers (route handlers).
*/
const homeController = require('./controllers/home');
const userController = require('./controllers/user');
const contactController = require('./controllers/contact');
const dashController = require('./controllers/dash');
const currencyController = require('./controllers/currency');
const accountController = require('./controllers/account');
const testController = require('./controllers/test');
const txController = require('./controllers/transaction');
/**
* API keys and Passport configuration.
*/
const passportConfig = require('./config/passport');
/**
* Create Express server.
*/
const app = express();
/**
* Express configuration.
*/
app.set('host', '127.0.0.1');
app.set('port', 8080);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(expressStatusMonitor());
app.use(compression());
app.use(sass({
src: path.join(__dirname, 'public'),
dest: path.join(__dirname, 'public')
}));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.use(session({
resave: true,
saveUninitialized: true,
secret: process.env.SESSION_SECRET,
cookie: { maxAge: 1209600000 }, // two weeks in milliseconds
store: new SequelizeStore({
db: models.sequelize
})
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use((req, res, next) => {
// if (req.path === '/api/upload') {
// next();
// } else {
// lusca.csrf()(req, res, next);
// }
next();
});
app.use(lusca.xframe('SAMEORIGIN'));
app.use(lusca.xssProtection(true));
app.disable('x-powered-by');
app.use((req, res, next) => {
res.locals.user = req.user;
next();
});
app.use((req, res, next) => {
// After successful login, redirect back to the intended page
if (!req.user
&& req.path !== '/login'
&& req.path !== '/signup'
&& !req.path.match(/^\/auth/)
&& !req.path.match(/\./)) {
req.session.returnTo = req.originalUrl;
} else if (req.user
&& (req.path === '/account' || req.path.match(/^\/api/))) {
req.session.returnTo = req.originalUrl;
}
next();
});
app.use('/', express.static(path.join(__dirname, 'public'), { maxAge: 31557600000 }));
app.use('/js/lib', express.static(path.join(__dirname, 'node_modules/chart.js/dist'), { maxAge: 31557600000 }));
app.use('/js/lib', express.static(path.join(__dirname, 'node_modules/popper.js/dist/umd'), { maxAge: 31557600000 }));
app.use('/js/lib', express.static(path.join(__dirname, 'node_modules/bootstrap/dist/js'), { maxAge: 31557600000 }));
app.use('/js/lib', express.static(path.join(__dirname, 'node_modules/jquery/dist'), { maxAge: 31557600000 }));
app.use('/webfonts', express.static(path.join(__dirname, 'node_modules/#fortawesome/fontawesome-free/webfonts'), { maxAge: 31557600000 }));
/**
* Primary app routes.
*/
app.get('/', homeController.index);
app.get('/login', userController.getLogin);
app.post('/login', userController.postLogin);
app.get('/logout', userController.logout);
app.get('/forgot', userController.getForgot);
app.post('/forgot', userController.postForgot);
app.get('/reset/:token', userController.getReset);
app.post('/reset/:token', userController.postReset);
app.get('/signup', userController.getSignup);
app.post('/signup', userController.postSignup);
// app.get('/account', passportConfig.isAuthenticated, userController.getAccount);
// app.post('/account/profile', passportConfig.isAuthenticated, userController.postUpdateProfile);
app.post('/account/password', passportConfig.isAuthenticated, userController.postUpdatePassword);
// app.post('/account/delete', passportConfig.isAuthenticated, userController.postDeleteAccount);
// app.get('/account/unlink/:provider', passportConfig.isAuthenticated, userController.getOauthUnlink);
app.get('/dashboard', passportConfig.isAuthenticated, dashController.index);
app.get('/test', passportConfig.isAuthenticated, testController.test);
// app.get('/contact', contactController.contact);
// app.post('/addContact', contactController.addContact);
// app.post('/editContact', contactController.editContact);
// app.get('/listContacts', contactController.listContacts);
// app.get('/listCurrency', currencyController.listCurrency);
// app.post('/addAccount', accountController.addAccount);
// app.post('/editAccount', accountController.editAccount);
// app.get('/listAccounts', accountController.listAccounts);
// app.get('/getTransactions', txController.getTransactions);
/**
* Error Handler.
*/
if (process.env.NODE_ENV === 'development') {
// only use in development
app.use(errorHandler());
} else {
app.use((err, req, res, next) => {
console.error(err);
res.status(500).send('Server Error');
});
}
/**
* Start Express server.
*/
models.sequelize.sync({}).then(() => {
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');
});
});
module.exports = app;
user.js
const { promisify } = require('util');
const crypto = require('crypto');
const nodemailer = require('nodemailer');
const passport = require('passport');
const models = require('../models');
const { User } = models;
const randomBytesAsync = promisify(crypto.randomBytes);
/**
* GET /login
* Login page.
*/
exports.getLogin = (req, res) => {
if (req.user) {
return res.redirect('/');
}
res.render('account/login', {
title: 'Login'
});
};
/**
* POST /login
* Sign in using email and password.
*/
exports.postLogin = (req, res, next) => {
req.assert('email', 'Email is not valid').isEmail();
req.assert('password', 'Password cannot be blank').notEmpty();
req.sanitize('email').normalizeEmail({ gmail_remove_dots: false });
const errors = req.validationErrors();
if (errors) {
req.flash('errors', errors);
return res.redirect('/login');
}
passport.authenticate('local', (err, user, info) => {
if (err) { return next(err); }
if (!user) {
req.flash('errors', info);
return res.redirect('/login');
}
req.logIn(user, (err) => {
if (err) { return next(err); }
res.locals.user = user; //Updated code after comment suggestions
req.flash('success', { msg: 'Success! You are logged in.' });
res.redirect('/dashboard');
});
})(req, res, next);
};
/**
* GET /logout
* Log out.
*/
exports.logout = (req, res) => {
req.logout();
req.session.destroy((err) => {
if (err) console.log('Error : Failed to destroy the session during logout.', err);
req.user = null;
res.redirect('/');
});
};
/**
* GET /signup
* Signup page.
*/
exports.getSignup = (req, res) => {
if (req.user) {
return res.redirect('/');
}
res.render('account/signup', {
title: 'Create Account'
});
};
/**
* POST /signup
* Create a new local account.
*/
exports.postSignup = (req, res, next) => {
req.assert('email', 'Email is not valid').isEmail();
req.assert('password', 'Password must be at least 4 characters long').len(4);
req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password);
req.sanitize('email').normalizeEmail({ gmail_remove_dots: false });
const errors = req.validationErrors();
if (errors) {
req.flash('errors', errors);
return res.redirect('/signup');
}
User.findAll({ limit: 1, where: { email: req.body.email }, plain: true })
.then((existingUser) => {
if (existingUser) {
req.flash('errors', { msg: 'Account with that email address already exists.' });
return res.redirect('/signup');
}
User.create({
email: req.body.email,
password: req.body.password
}).then((user) => {
req.logIn(user, (err) => {
if (err) { return next(err); }
res.locals.user = user; //updated code after comment suggestions
return res.redirect('/');
});
}).catch(error => next(error));
});
};
passport.js
const passport = require('passport');
const request = require('request');
const { Strategy: LocalStrategy } = require('passport-local');
const _ = require('lodash');
const models = require('../models');
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
models.User.findAll({ where: { id }, limit: 1, plain: true })
.then(user => done(null, user))
.catch(err => done(err));
});
/**
* Sign in using Email and Password.
*/
passport.use(new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
models.User.findAll({ where: { email }, limit: 1, plain: true }).then((user) => {
if (!user) {
return done(null, false, { msg: `Email ${email} not found.` });
}
user.comparePassword(password, (err, isMatch) => {
if (err) { return done(err); }
if (isMatch) {
return done(null, user);
}
return done(null, false, { msg: 'Invalid email or password.' });
});
}).catch(error => done(error));
}));
/**
* OAuth Strategy Overview
*
* - User is already logged in.
* - Check if there is an existing account with a provider id.
* - If there is, return an error message. (Account merging not supported)
* - Else link new OAuth account with currently logged-in user.
* - User is not logged in.
* - Check if it's a returning user.
* - If returning user, sign in and we are done.
* - Else check if there is an existing account with user's email.
* - If there is, return an error message.
* - Else create a new account.
*/
/**
* Login Required middleware.
*/
exports.isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/login');
};
/**
* Authorization Required middleware.
*/
exports.isAuthorized = (req, res, next) => {
const provider = req.path.split('/').slice(-1)[0];
const token = req.user.tokens.find(token => token.kind === provider);
if (token) {
next();
} else {
res.redirect(`/auth/${provider}`);
}
};
In your app.js, you need to call const passportConfig = require('./config/passport'); after you initialize passport, like so:
app.use(passport.initialize());
app.use(passport.session());
// place it here
const passportConfig = require('./config/passport')(passport);
Further, you need to adjust your password config file (./config/passport), so that on module loading it can get the passport instance that you instantiated in app.js, and subsequently uses it instead of loading a new passport instance via require('passport') - this in my opinion messes things up; didn't test it though. :)
Can you share the user object sample which refer to this code in your passport.js LocalStrategy
user.comparePassword(password, (err, isMatch) => {....});
looks like user.id is not available in serializeuser below which may be the cause it cant set user.id in the session and cant deserialize User further not setting the user object in req
passport.serializeUser((user, done) => {
done(null, user.id);
});

API Route available with Any token JWT+PASSPORT

I'm building api for my app and trying to use passport jwt.
I can register new users and login(get the token back) but when I use the Postman to check the "protected" route I can use Any Token like this 'any any'
Pasport.js
const JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
const User = require('../api/models/user/userModel'),// load up the user model
config = require('../config/database'); // get db config file
module.exports = (passport)=> {
let opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
User.findOne({id: jwt_payload.id}, (err, user)=> {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false);
}
});
}));
};
Server.js
const express = require('express'),
app = express(),
port = process.env.PORT || 3000,
mongoose = require('mongoose'),
morgan = require('morgan'),
passport = require('passport'),
bodyParser = require('body-parser'),
jwt = require('jsonwebtoken'),
config = require('./config/database'),
Event = require('./api/models/event/eventModel'),
User = require('./api/models/user/userModel');
mongoose.Promise = global.Promise;
mongoose.connect(config.database);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(passport.initialize());
/* Routers registration */
const routesEvent = require('./api/routes/event/eventRoutes');
routesEvent(app);
const routesUser = require('./api/routes/user/userRoutes');
routesUser(app);
/* END Routers registration */
/* Express middleware
* which used to return more interactive messages */
app.use((req, res, next)=>{
res.status(404).send({url: req.originalUrl + ' not found'});
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
/* END Express middleware */
// Launch the server on port 3000
const server = app.listen(3000, () => {
const { address, port } = server.address();
console.log(`RESTful API server Listening at http://${address}:${port}`);
});
EventRouter.js
const jwt = require('jsonwebtoken'),
passport = require('passport');
require('../../../config/passport')(passport); // as strategy in ./passport.js needs passport object
module.exports = (app)=> {
const event = require('../../controllers/event/eventController');
// Routes
app.route('/events' )
.get( event.list_all_events, passport.authenticate('jwt', { session: false}));
};
EventController
const mongoose = require('mongoose'),
Event = mongoose.model('Events'),
getToken = require('../../../config/getToken');
exports.list_all_events = (req, res)=> {
let token = getToken(req.headers);
if(token){
Event.find({}, (err, event)=> {
if (err)
res.send(err);
res.json(event);
});
} else {
return res.status(403).send({success: false, msg: 'Unauthorized.'});
}
};
I'm definitely doing something wrong in controller or in this file
GetToken.js
module.exports = getToken = (headers)=> {
console.log(headers);
if (headers && headers.authorization) {
let parted = headers.authorization.split(' ');
//Here I can see my Token from the Postman
if (parted.length === 2) {
return parted[1];
} else {
return null;
}
} else {
return null;
}
};
Please, any ideas about a mistake that I'm making above?
Below line act as an middle ware. It is validating JWT token, once token is validated it will call JwtStrategy and setting user object in request and then it will call the actual function which is suppose to be executed.
passport.authenticate('jwt', { session: false})
You really do not need getToken function. It will be taken care by above line. If token is not validated then above line automatically returns 401.
Looks strange but when I changed code to this
EventRouter.js
app.route('/events' )
.get( passport.authenticate('jwt', { session: false}), event.list_all_events)
.post(event.create_event);
It's works like expected
The only one difference is the order in get(passport, function)

Categories