I'm having issues getting Passport to work with RethinkDB. I'm trying to authenticate using passport-local and based my solution on this tutorial: Passport Tutorial with RethinkDB
I keep getting the response Bad Request
The structure of my node modules are as follows:
- server
- auth
- auth-controller.js
- auth-router.js
- index.js
- db
- index.js
- views
- index.html
- index.js
auth/auth-controller.js
var authController = {};
authController.getUser = function (req, res) {
if (req.user && req.user.id) {
res.json(req.user);
return;
}
res.status(400).json(null);
};
authController.logout = function (req, res) {
req.logout();
res.redirect('/');
};
authController.login = function (req, res) {
res.redirect('/');
};
module.exports = authController;
auth/auth-router.js
var express = require('express');
var authControllers = require('./auth-controller');
var auth = require('./index');
var authRouter = express.Router();
// Local
authRouter.use('/login/callback/local', auth.authenticate('local'), function (req, res) {
res.redirect('/');
});
authRouter.post('/login/local', auth.authenticate('local'));
// All
authRouter.use('/user', authControllers.getUser);
authRouter.use('/logout', authControllers.logout);
module.exports = authRouter;
auth/index.js
var config = require('config');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var r = require('../db');
passport.serializeUser(function (user, done) {
return done(null, user.id);
});
passport.deserializeUser(function (id, done) {
r
.table('Users')
.get(id)
.run(r.conn)
.then(function (user) {
done(null, user);
});
});
var loginCallbackHandler = function (objectMapper) {
return function (accessToken, refreshToken, profile, done) {
if (accessToken !== null) {
r
.table('Users')
.getAll(profile.username, { index: 'username' })
.run(r.conn)
.then(function (cursor) {
return cursor.toArray()
.then(function (users) {
if (users.length > 0) {
return done(null, users[0]);
}
return r.table('Users')
.insert(objectMapper(profile))
.run(r.conn)
.then(function (response) {
return r.table('Users')
.get(response.generated_keys[0])
.run(r.conn);
})
.then(function (newUser) {
done(null, newUser);
});
});
})
.catch(function (err) {
console.log('Error Getting User', err);
});
}
};
};
var callbackURL = 'http://' + config.get('url') + ':' + config.get('ports').http + '/auth/login/callback/login';
// Local
passport.use(new LocalStrategy({
callbackURL: callbackURL
},
loginCallbackHandler(
function (profile) {
return {
'username': profile.username,
'password': profile.password
};
}
)
));
passport.checkIfLoggedIn = function (req, res, next) {
if (req.user) {
return next();
}
return res.status(401).send('You\'re not logged in');
};
module.exports = passport;
db/index.js
var r = require('rethinkdb');
require('rethinkdb-init')(r);
var config = require('config');
r.connections = [];
r.getNewConnection = function () {
return r.connect(config.get('rethinkdb'))
.then(function (conn) {
conn.use(config.get('rethinkdb').db);
r.connections.push(conn);
return conn;
});
};
r.init(config.get('rethinkdb'), [
{
name: 'Users',
indexes: ['username']
}
]).then(function (conn) {
r.conn = conn;
r.connections.push(conn);
r.conn.use(config.get('rethinkdb').db);
});
module.exports = r;
views/index.html
<body>
<h1>Passport/RethinkDB Example</h1>
{{#user}}
<img style='width: 100px; height: 100px;' src='{{ avatarUrl }}'>
<p>You are logged in as <span style="font-weight: bold;">{{ login }}</span>. Account created through <span style="font-weight: bold;">{{ type }}</span>.</p>
<a href='/auth/user'>See user data</a>
</br>
<a href='/auth/logout'>Logout</a>
{{/user}}
{{^user}}
<p>You are not logged in.</p>
<form action="/auth/login/local" method="post">
Username: <input type="text" name="username" value="sam"><br>
Password: <input type="text" name="password" value="123"><br>
<input type="submit" value="Submit">
</form>
{{/user}}
</body>
index.js
var config = require('config');
var express = require('express');
var session = require('express-session');
var engines = require('consolidate');
var app = express();
var auth = require('./auth');
var authRouter = require('./auth/auth-router');
// Middleware
app
.use(session({
secret: '#########',
resave: false,
saveUninitialized: true
}))
.use(auth.initialize())
.use(auth.session());
// Views
app
.set('views', __dirname + '/views')
.engine('html', engines.mustache)
.set('view engine', 'html');
// Routes
app
.use('/auth', authRouter)
.get('/', function (req, res) {
res.render('index.html', { user: req.user });
})
.use(express.static(__dirname + '/../client'))
.use('*', function (req, res) {
res.status(404).send('404 Not Found').end();
});
app.listen(config.get('ports').http);
What have I done to cause the Bad Request issue and is there an easy way to debug this?
The Bad Request occurs when I submit the username and password from the form... this is the url I believe it happens at ../auth/login/local
You don't show your server code. I had a similar problem once and it was because my bodyparser wasn't set up in the server:
const bodyParser = require('body-parser');
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
Or something like that. POST requests send info through the body. If that doesn't work, it would be nice to see your server code.
Related
After implementing using passport-local not able to open profile page
I'm getting this below error
This page isn’t workinglocalhost redirected you too many times.
Try clearing your cookies.
ERR_TOO_MANY_REDIRECTS
passport-local-strategy.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/user');
passport.use(new LocalStrategy({
usernameField: 'email'
},
function(email, password, done){
User.findOne({email: email}, function(err, user){
if(err){
console.log('Error in finding user --> Passport');
return done(err);
}
if(!user || user.password!=password){
console.log("Invalid username/password");
return done(null, false);
}
return done(null, user);
});
}
));
// serialize user function
passport.serializeUser(function(user, done){
done(null, user.id);
});
//deserialize the user fn
passport.deserializeUser(function(id, done){
User.findById(id, function(err, user){
if(err){
console.log("Error in finding user --> passport");
return done(err);
}
return done(null, user);
});
});
// check if user is authenticated
passport.checkAuthenticated = function(req, res, next){
if(req.isAuthenticated()){
return next();
}
// if the user is not signed in
return res.redirect('/users/sign-in');
}
passport.setAuthenticatedUser = function(req, res, next){
if(req.isAuthenticated()){
// req.user contains current signed in user data from the login page
res.locals.user = req.user;
}
next();
}
module.exports = passport;
users_controller.js
const User = require('../models/user')
module.exports.profile = function(req, res){
if(req.cookies.user_id){
User.findById(req.cookies.user_id, function(err, user){
if(user){
return res.render('profile',{
title:"Profile",
user:user
});
}
else{
return res.redirect('/users/sign-in')
}
})
}
else{
return res.redirect('/users/sign-in');
}
}
// render the sign up and in page
module.exports.signUp = function(req, res){
if(req.isAuthenticated()){
return res.redirect('/users/profile')
}
return res.render('user_sign_up', {
title: "Codeial | Sign Up"
})
}
module.exports.signIn = function(req, res){
if(req.isAuthenticated()){
return res.redirect('/users/profile')
}
return res.render('user_sign_in', {
title: "Codeial | Sign In"
})
}
// get the sign up data
module.exports.create = function(req, res){
if(req.body.password != req.body.confirm_password){
return res.redirect('back')
}
User.findOne({email:req.body.email}, function(err, user){
if(err){console.log('error in finding user in signing up'); return;}
if(!user){
User.create(req.body, function(err, user){
if(err){console.log('error in finding user in signing up'); return;}
return res.redirect('/users/sign-in')
})
}
else{
return res.redirect('back')
}
})
}
module.exports.createSession = function(req, res){
return res.redirect('/');
}
users.js
const express = require('express')
const router = express.Router();
const passport = require('passport');
const usersController = require('../controllers/users_controller');
router.get('/profile',passport.checkAuthenticated,usersController.profile)
router.get('/sign-up', usersController.signUp);
router.get('/sign-in', usersController.signIn);
// in above all codes after get('/sign-up') means when we type the keyword sign-up in the browser we need to render the folllowing page which is userController.signUp
// we are using users_controller.js file by importing
router.post('/create', usersController.create);
router.post('/create-session',passport.authenticate(
'local',
{failureRedirect: '/users/sign-in'},
),usersController.createSession);
// above line post create-session is forms action in user_sign_in.ejs file - when we submit the data of the form the post method is invoked
module.exports = router;
mongoose.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/codeial_development')
const db = mongoose.connection;
db.on('error', console.error.bind(console, "Error connecting to MongoDb"));
db.once('open', function(){
console.log('connected to the database :: MongoDB ')
})
module.exports = db;
index.js
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
const port = 8000;
const expressLayouts = require('express-ejs-layouts');
const db = require('./config/mongoose')
const session = require('express-session');
const passport = require('passport');
const passportLocal = require('./config/passport-local-strategy')
const MongoStore = require('connect-mongodb-session')(session)
app.use(express.urlencoded());
/* is a method inbuilt in express to recognize the incoming
Request Object as strings or arrays. This method is called as a
middleware in your application using the code*/
app.use(cookieParser());
app.use(express.static('./assets'));
app.use(expressLayouts);
// extact style and scripts from subpages into the layout
app.set('layout extractStyles', true)
app.set('layout extractScripts', true)
app.set('view engine', 'ejs');
app.set('views','./views')
app.use(session({
name: 'codeial',
secret:'blahsomeone',
saveUninitialized:false,
resave:false,
cookie:{
maxAge: (1000 * 60 * 100)
},
store: new MongoStore({
// mongooseConnection:db
mongoUrl: db._connectionString,
autoRemove: 'disabled'
}, function(err){
console.log(err || 'connect-mongo setup ok')
})
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(passport.setAuthenticatedUser);
// use express router
app.use('/', require('./routes'));
app.listen(port, function(err){
if(err){console.log(`Error running the server: ${err}`)};
console.log(`Server is running on port: ${port}`);
})
I'm not able to view profile page, its redirecting or getting this error
This page isn’t workinglocalhost redirected you too many times.
Try clearing your cookies.
ERR_TOO_MANY_REDIRECTS
Im making a dashboard for a Discord Bot, but i keep getting the error TypeError: Cannot read property 'method' of undefined. The code of my app is:
const http = require('http');
const path = require('path');
const client = require("./Client");
const express = require('express');
const reqip = require('request-ip');
const passport = require('passport');
const Discord = require('discord.js');
const session = require('express-session');
const getFilesSync = require("..//Utils/fileWalk");
const SQLiteStore = require("connect-sqlite3")(session);
const { Strategy } = require('passport-discord').Strategy;
const port = process.env.port || 80;
class App {
constructor(locals = {}) {
this.express = express();
this.express.set("view engine", "ejs");
this.express.set("port", port);
this.express.set("json spaces", 2);
this.express.locals = locals;
/ * MiddleWare Functions * /;
this.express.use(express.json());
this.express.use(express.urlencoded({
extended: false
}))
this.express.use(reqip.mw());
this.express.use('/assets', express.static(__dirname + "/../Assets"));
bindAuth(this.express, client);
this.express.use(passport.initialize());
this.express.use(passport.session());
this.express.use(async (req, res, next) => {
req.bot = client;
next();
});
this.loadRoutes().loadErrorHandler();
}
listen(port) {
return new Promise((resolve) => this.express.listen(port, resolve));
}
loadRoutes() {
const routesPath = path.join(__dirname, "../routes");
const routes = getFilesSync(routesPath);
if (!routes.length) return this;
routes.forEach((filename) => {
const route = require(path.join(routesPath, filename));
const routePath =
filename === "index.js" ? "/" : `/${filename.slice(0, -3)}`;
try {
this.express.use(routePath, route);
} catch (error) {
console.error(`Error occured with the route "${filename}"\n\n${error}`);
}
});
return this;
}
loadErrorHandler() {
this.express.use((req, res) => {
res.status(404);
if (req.accepts("html")) return res.render("404", {req});
if (req.accepts("json"))
return res.send({
status: 404,
error: "Not found",
});
res.type("txt").send("404 - Not found");
});
return this;
}
}
function bindAuth(app, client) {
app.use(session({store: new SQLiteStore(), secret: "nosecretlol", resave: false, saveUninitialized: false}))
passport.serializeUser(function(user, done) {
done(null, user);
})
passport.deserializeUser(function(obj, done) {
done(null, obj);
})
passport.use(
new Strategy(
{
clientID: process.env.bot_id,
clientSecret: process.env.bot_secret,
callbackURL: process.env.bot_redirect,
scope: ["identify", "guilds"]
},
function(accessToken, refreshToken, profile, done) {
process.nextTick(function() {
profile.tokens = { accessToken }
return done(null, profile)
})
})
)
}
module.exports = App;
And in my index i make my app like this:
const App = require("myfile");
(async () => {
await new App().listen(process.env.port || 80)
})()
The error says is in: node_modules\express\lib\router\index.js:139:34)
I tried with all and i cannot solve this, i asked many persons but no ones give me a answer that can solve my question.
Like i said this is for a Discord Bot Dashboard
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.
I am trying to make a get request with ajax, it doesn't seem to run the code in my NodeJS /tools route, maybe someone can enlighten me. I am looking to run a script from nodeJS from an AJAX request. xhr GET request doesn't seem to work with to initiate the that console log in the nodejs route.
These are my routes.
const express = require('express');
const router = express.Router();
const User = require('../models/user.js');
const mid = require('../middleware');
const axios = require('axios');
// Home Routes
router.get('/', (req, res, next) => {
res.render('index');
});
// About Routes
router.get('/about', (req, res, next) => {
res.render('about', {title : '| About'});
});
// Tools Routes
router.get('/tools', (req, res, next) => {
console.log("ajax request went through!");
});
router.post('/tools', (req, res, next) => {
var domain = req.body.domain;
canYouDigIt(domain);
});
router.get('/map', (req, res, next) => {
res.render('map');
});
// Login Routes
router.get('/login', mid.loggedOut, (req, res, next) => {
res.render('login', {title : '| Log in'});
});
router.post('/login', (req, res, next) => {
if ( req.body.email && req.body.password) {
User.authenticate(req.body.email, req.body.password, function(error, user){
if (error || !user) {
var err =new Error('Wrong email or password.');
err.status = 401;
return next(err);
} else {
req.session.userId = user._id;
return res.redirect('/profile');
}
});
} else {
var err =new Error('Email and password are required!');
err.status = 401;
return next(err);
}
});
// Logout Routes
router.get('/logout', (req, res, next) => {
if (req.session){
// Delete Session
req.session.destroy(function(err) {
if(err) {
return next(err);
} else {
return res.redirect('/');
}
});
}
});
// Registration Routes
router.get('/registration', mid.loggedOut, (req, res, next) => {
res.render('registration', {title : '| Registration'});
});
router.post('/registration', (req, res, next) => {
// Check if all fields are filled
if (req.body.userName && req.body.password && req.body.confirmPassword && req.body.firstName && req.body.lastName && req.body.email) {
// Confirm Password is the same
if ( req.body.password != req.body.confirmPassword) {
const err = new Error ("Passwords don't match!");
err.status = 400;
return next(err);
};
const userData = {
userName: req.body.userName,
password: req.body.password,
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email
};
// Use schema 'create' method to insert document into Mongo
User.create(userData, (error, user) => {
if (error) {
return next(error);
} else {
req.session.userId = user._id;
return res.redirect('/profile');
}
});
} else {
const err = new Error("All Fields Required.");
err.status = 400;
return next(err);
}
});
module.exports = router;
This is my html/pug calling the route
section(id="digToolWrapper")
form( id="digToolInput" )
ul
li #[input(id="digTool" name="domain" type="text" placeholder="Can you dig it?")]#[input(id="whois" value="whois" type="button" onclick="digIt()")]
This is my ajax request
function digIt() {
var xhr = new XMLHttpRequest();
var domain = document.getElementById("digTool").value;
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(domain);
}
};
xhr.open('GET', '/tools', true);
console.log(domain);
xhr.send();
};
App.js file
const express = require('express');
const session = require('express-session');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const path = require('path');
const mongoose = require('mongoose');
const MongoStore = require('connect-mongo')(session);
const axios = require('axios');
const app = express();
// Mongodb connection
mongoose.connect("mongodb://localhost:27017/nymadic", { useNewUrlParser: true });
const db = mongoose.connection
// Mongo error
db.on('error', console.error.bind(console, 'connection error:'));
// Use sessions for tracking logins
app.use(session({
secret: 'keyboard cat!',
resave: true,
saveUninitialized: false,
// This stores sessions in the Mongo DB so the server doesnt become overloaded
store: new MongoStore({
mongooseConnection: db
})
}));
// Make user ID available in template
app.use(function (req, res, next){
res.locals.currentUser = req.session.userId;
next();
});
// Body Parser and Cookie Parser
app.use(bodyParser.urlencoded({ extended:false }));
app.use(cookieParser());
// Static Files
app.use(express.static(__dirname + '/public'));
// Pug Render Engine
app.set('view engine', 'pug');
// Routes
const mainRoutes = require('./routes');
const profileRoutes = require('./routes/profile');
const wikiRoutes = require('./routes/wiki');
app.use(mainRoutes);
app.use('/profile', profileRoutes);
app.use('/wiki', wikiRoutes);
app.listen(8080, () => {
console.log('Nodejs is running on port 8080...');
});
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