Implementing LocalStorage into an authentication form in express and ejs - javascript

I am making a authentication form were users can register and login.
if (process.env.Node_ENV !== 'production') {
require('dotenv').config()
}
const express = require('express');
const app = express();
const bcrypt = require('bcrypt')
const passport = require("passport")
const flash = require("express-flash")
const sessions = require("express-session")
const methodOverride = require("method-override")
const fs = require('fs')
const initializePassport = require("./passport-config")
initializePassport(
passport,
email => users.find(user => user.email === email),
id => users.find(user => user.id === id)
)
const users = []
app.set("view-engine", "ejs")
app.use('/public', express.static('public'))
app.use(express.urlencoded({extended: false}))
app.use(flash())
app.use(sessions({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride('_method'))
app.get("/", checkAuthenticated, (req,res)=> {
res.render("index.ejs", { name: req.user.name})
})
app.get("/login", checkNotAuthenticated, (req, res) => {
res.render("login.ejs")
})
app.post("/login", checkNotAuthenticated, passport.authenticate('local', {
successRedirect: "/",
failureRedirect: "/login",
failureFlash: true
}))
app.get("/register", checkNotAuthenticated, (req,res)=> {
res.render("register.ejs")
})
app.post("/register", checkNotAuthenticated, async (req,res) => {
try{
//encrypt the Uses password, so "we" cant see it
const hashedPassword = await bcrypt.hash(req.body.password, 10)
users.push({
id: Date.now().toString(),
name: req.body.name,
email: req.body.email,
password: hashedPassword
})
//if all the above is right, than redirect the user to login page
res.redirect("/login")
}catch{
//if for some reason there is a failure, redirect back to register
res.redirect("/register")
}
//if there is user that is added, it is possible to see ind the console
//console.log(users)
localStorage.setItem('user', JSON.stringify(users));
})
app.delete('/logout', (req,res) => {
req.logOut()
res.redirect('/login')
})
function checkAuthenticated(req, res, next){
if (req.isAuthenticated()) {
return next()
}
res.redirect('/login')
}
function checkNotAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return res.redirect('/')
}
next()
}
The problem is that I need to implement localStorage, and the user needs to be able to delete the account once they are logged in.
To register the user only needs "Name", "email" and "password"
here is some of my passport-config if necessary:
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require("bcrypt")
function initialize(passport, getUserByEmail, getUserById){
const authenticateUser = async (email, password, done) => {
const user = getUserByEmail(email)
if (user == null) {
return done(null, false, {message: "No user with that Email"})
}
try{
if(await bcrypt.compare(password, user.password)) {
return done(null, user)
} else{
return done(null, false, {message: "Passwrod incorrect"})
}
}catch(error){
return done(error)
}
}
passport.use(new LocalStrategy({usernameField: 'email'}, authenticateUser))
passport.serializeUser((user,done) => done(null, user.id))
passport.deserializeUser((id,done) => {
return done(null, getUserById(id))
})
}
module.exports = initialize;
Everything works fine, so there is no error in the code it's self, I just don't seem to find an answer to what I need to do anywhere, I can only find mongoDB which I don't want to use. The most important for me is to implement the localStorage, then it comes the delete part.
I hope some of you can help me!
Thanks a lot.

Related

resolve TypeError: req.flash is not a function?

Working with Registration in a Site. For the register Form,Validation is done using mongoose models and trying to Use Flash to display the error message in the Form.
In my nodejs app it shows an error like:
TypeError: req.flash is not a function
I have installed connection-flash npm it is throwing an error like:
TypeError: req.flash is not a function at
E:\node-course\apnadukan\src\routes\index.js:21:24
app.js
const express = require('express');
const path = require('path');
const hbs = require('hbs');
const flash = require("connect-flash");
const passport = require("passport");
const db = require('./connection/db');
// Express Use
const app = express()
const port = 3000;
// Form Data Get
app.use(express.json());
app.use(express.urlencoded({extended:false}));
// HBS Handlebar use
app.set('view engine', 'hbs');
// Router Use
app.use('/', require(path.join(__dirname, 'routes/index.js')))
// Publics assess link (HBS)
const static_path = path.join(__dirname, '../publics');
app.use(express.static(static_path));
// View Set (HBS)
const views = path.join(__dirname, '../src/views');
const partials_path = path.join(__dirname, '../src/views/partials');
app.set('views', views);
hbs.registerPartials(partials_path);
//
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
index.js
const express = require('express');
const addUser = require('../models/register');
let passport = require("passport");
let LocalStrategy = require("passport-local").Strategy;
// const passport = require('../config/passport');
const {validationRegister, validationRegisterMsg} = require('../config/validator');
// const router = express.Router()
const router = require('express').Router()
router.get('/' , (req , res)=>{
res.render('index', {
title: "Welcome To Apna Dukan"
})
})
router.get('/welcome-to-apnadukan', (req , res)=>{
var errorMsg = req.flash('error')[0];
res.render('register', {
title: "Register | Welcome To Apna Dukan",
errorMsg,
page_name: "Register"
});
});
router.post('/welcome-to-apnadukan',
[
validationRegister(),
validationRegisterMsg,
passport.authenticate("local.register", {
successRedirect: "/login",
failureRedirect: "/welcome-to-apnadukan",
failureFlash: true,
}),
],
async (req , res)=>{
try {
if (req.session.oldUrl) {
let oldUrl = req.session.oldUrl;
req.session.oldUrl = null;
res.redirect(oldUrl);
} else {
res.redirect("/welcome-to-apnadukan");
}
} catch (error) {
req.flash("error", error.message);
res.status(400).send(error);
return res.redirect("/");
}
})
router.get('/login' , (req , res)=>{
res.render('login', {
title: "Login | Welcome To Apna Dukan",
page_name: "Login"
})
})
router.post('/login' , (req , res)=>{
req.send("Update");
})
router.get('/recover-password', (req, res)=>{
res.render('recoverpassword',{
title: "Recover Password | Welcome To Apna Dukan",
page_name: "Recover Password"
})
})
router.post('/recover-password', (req, res)=>{
res.render('recoverpassword',{
title: "Recover Password | Welcome To Apna Dukan",
page_name: "Recover Password"
})
})
router.get('/page' , (req , res)=>{
res.send('Hello World!')
})
module.exports = router
Validator.js
const { check, validationResult } = require("express-validator");
const validationRegister = (()=>{
return [
check('name', 'Name is required').not().isEmpty(),
check('username', 'Username is required').not().isEmpty().matches('/^(?![0-9]*$)[a-zA-Z0-9]+$/').withMessage('Only AlphaNumeric character is allowed').isLength({min:6,max:6}).withMessage('Minimum 6 characters required'),
check('email', 'Email is required').not().isEmpty().isEmail().withMessage('Email must be a valid email address.'),
check('password', 'Password is required').not().isEmpty().matches('/^(?=(.*[a-zA-Z].*){2,})(?=.*\d.*)(?=.*\W.*)[a-zA-Z0-9\S]{6,}$/').withMessage('Strong passwords with min 6 characters, at least two letters (not case sensitive), one number, one special character, space is not allowed'),
];
});
const validationRegisterMsg = (req, res, next)=>{
const errors = validationResult(req);
if (!errors.isEmpty()) {
let messages = [];
errors.array().forEach((error)=>{
messages.push(error.msg)
});
req.flash('error', messages);
// req.flash({error: messages})
return res.redirect('/register');
}
next();
};
module.exports = {validationRegister,validationRegisterMsg};
passport.js
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const User = require("../models/register");
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
passport.use(
"local.register",
new LocalStrategy(
{
nameField: 'name',
usernameField: 'username',
emailField: 'email',
passwordField: 'password',
passReqToCallBack: true
},
async (req, username, email, done) => {
try {
const username = await Customer_users.findOne({ username: username });
if (username) {
return done(null, false, { message: "Username already exists" });
}
const user = await Customer_users.findOne({ email: email });
if (user) {
return done(null, false, { message: "Email already exists" });
}
const newUser = await new User();
newUser.name = name;
newUser.username = username;
newUser.email = email;
newUser.password = newUser.encryptPassword(password);
await newUser.save();
return done(null, newUser);
} catch (error) {
console.log(error);
return done(error);
}
}
)
);
You are configuring flash in your app after configuring the routes.
Moving this line app.use(flash()); before line app.use('/', require(path.join(__dirname, 'routes/index.js'))); will resolve the issue.

What do I do with this 'session' created by passport.js?

I am implementing user authentication and and once they are authenticated, they can CRUD their user data on the database. I can currently authenticate users and have users register a new account, but im not sure what my next step should be. What should my Node server pass back to my front end once my user is authenticated? I read everywhere that I am suppose to use tokens and sessions to check if user is auth for every request.
Auth.js
const router = express.Router()
const passport = require("passport")
router.post("/login", (req, res, next) => {
passport.authenticate("local", function(err, user, info) {
console.log(user)
if(err){
return res.status(400).json({errors: err})
}
if(!user){
return res.status(400).json({errors: "Incorrect username or password"})
}
//figure out what this does
req.logIn(user, function(err){
if(err){
return res.status(400).json({errors: err});
}
return res.status(200).json({success: `Logged in ${user.id}`})
})
})(req, res, next)
})
module.exports = router
Setup.js (for passportjs)
const bcrypt = require("bcrypt")
const User = require('../models/user')
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
passport.serializeUser((user, done) => {
done(null, user.id)
})
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
})
})
passport.use(
new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
//Match user
User.findOne({ email: email })
.then(user => {
//match password
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
console.log("successfully auth")
return done(null, user);
} else {
console.log("incorrect password ")
return done(null, false, { message: "Incorrect Password" })
}
})
})
.catch(err => {
console.log("no account found")
return done(null, false, { message: err })
})
})
)
module.exports = passport
index.js
require('dotenv').config()
const express = require('express');
const session = require('express-session');
const mongoose = require("mongoose")
const MongoStore = require("connect-mongo")
const cors = require("cors");
const axios = require('axios');
const User = require('./models/user')
const bcrypt = require('bcrypt')
const passport = require("./passport/setup")
const auth = require("./routes/auth")
const app = express();
app.use(cors());
let port = process.env.PORT;
if (port == null || port == "") {
port = 5000;
}
mongoose.connect(process.env.ATLAS_URI).then(console.log("MongoDB Connection Success")).catch(err => console.log("MongoDB Connection Failed" + err))
// For backend and express init
app.use(express.json());
app.use(express.urlencoded({ extended: false }))
app.use(session({
secret: 'random secret',
resave: false,
saveUninitialized: true,
store: MongoStore.create({ mongoUrl: process.env.ATLAS_URI }),
}));
app.use(passport.initialize())
app.use(passport.session())
app.use("/auth", auth)
app.post('/register', (req, res) => {
const email = req.body.email
const plainTextPassword = req.body.password;
//check if user already exists
User.find({ name: email }, (err, existingUser) => {
if (existingUser.length === 0) {
bcrypt.hash(plainTextPassword, 8, async (err, hash) => {
try {
const user = new User({
email: email,
password: hash
});
let result = await user.save();
if (result) {
console.log("account registered successfully")
res.send(result)
}
} catch (e) {
res.send("Something Went Wrong");
console.log("something went wrong ---" + e)
}
})
} else {
console.log("user account already exists! Login instead. ")
}
})
})
Im not trying to debug an error, just need to know what the approach is. Basically, I want the user to login once, and then be able to navigate around the web app and crud to their database. Thank you!!
My sessions are stored in a different collection in mongodb but idk what to do with this

How do I get the email of the user who is logged in?

my problem is that I want to access to the user who is logged in. All users are saved in a database and then SELECTED into a variable.
In the passport-config-js I am checking the login by comparing the email and the hashed password. So I hope you all can help me, I need this for a school project.
severs.js
const express = require('express');
const app = express();
const bcrypt = require('bcrypt');
const passport = require('passport');
const flash = require('express-flash');
const session = require('express-session');
const methodOverride = require('method-override');
const initializePassport = require('./passport-config');
initializePassport(
passport,
email => users.find(user => user["email"] === email),
id => users.find(user => user["id"] === id)
)
const users = [];
app.set('view-engine', 'ejs');
app.use(express.urlencoded({extended: false}))
app.use(flash());
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(methodOverride('_method'));
app.use(express.static("public"))
app.get('/' , checkAuthenticated,(req, res) => {
res.render('startseite.ejs')
})
app.get('/login', checkNotAuthenticated ,(req, res) =>{
res.render('login.ejs');
})
app.post('/login', checkNotAuthenticated ,passport.authenticate('local',
{
successRedirect: '/startseite',
failureRedirect: '/login',
failureFlash: true
})
)
app.get('/startseite',checkAuthenticated,(req, res) =>{
res.render('startseite.ejs', {email: req.body.email});
console.log(req.body);
})
app.post('/register', checkNotAuthenticated,async (req, res, next) =>{
try {
const hashedPassword = await bcrypt.hash(req.body.password, 10);
let newUser = {
id: Date.now().toString(),
name: req.body.name,
email: req.body.email,
password: hashedPassword
}
if(users.length){
for(let i = 0; i < users.length; i+
if(req.body.email === users[i].email){
console.log(users[i].email + " email already taken");
alert("Email already taken");
res.render('/register');
}
}
}
let sql = `INSERT INTO Players (email, name, password) VALUES ('${newUser.email}', '${newUser.name}', '${newUser.password}')`;
connection.query(sql, (err, result) =>{
if(err) throw err;
console.log("User with email: " + newUser.email + " inserted")
allPlayers();
});
res.redirect('/login');
} catch {
res.redirect('/register');
}
//console.log(users);
})
app.delete('/startseite', (req, res) =>{
req.logOut();
res.redirect('/login');
})
function checkAuthenticated(req, res, next) {
if(req.isAuthenticated()){
return next()
}
res.redirect('/login');
}
function checkNotAuthenticated(req, res, next) {
if(req.isAuthenticated()){
return res.redirect('/');
}
next();
}
function allPlayers(){
let userList = query("*");
userList
.then()
.then((values) =>{
let i = 0;
while(values[i] != null){
users.push(values[i]);
i++;
}
//console.log(users);
})
}
allPlayers();
app.listen(3000);
passport-config.js
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcrypt');
const {connection, select, query} = require('./db');
function initialize(passport, getUserByEmail, getUserById){
const authenticateUser = async (email, password, done) =>{
const user = getUserByEmail(email);
if(user == null){
return done(null, false, {message: 'email or password incorrect'});
}
try {
if(await bcrypt.compare(password, user.password)) {
return done(null, user);
} else {
return done(null, false, {message: 'email or password incorrect'})
}
} catch(e) {
return done(e)
}
}
passport.use(new LocalStrategy({usernameField: 'email'},
authenticateUser));
passport.serializeUser((user, done) => done(null, user.id))
passport.deserializeUser((id, done) => {return done(null, getUserById(id))})
}
module.exports = initialize;

oauth20 is working properly but passport local not working

this is my local strategy configuration
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const LocalUsers = require('../db/localUser')
const bcrypt = require('bcrypt')
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
(username, password, done) => {
LocalUsers.findOne({ email: username }, async (err, user) => {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect email.' });
}
const matchedPassword = await bcrypt.compare(password, user.password)
if (!matchedPassword) {
return done(null, false, { message: 'Incorrect password.' });
}
else{
return done(null, user);
}
});
}
));
passport.serializeUser(function (user, done) {
return done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
await LocalUsers.findById(id, function (err, user) {
done(err, user);
});
});
and this is the server file
require('dotenv').config()
const express = require('express')
const app = express()
const authRoute = require('./routes/auth')
const loginRoute = require('./routes/login')
const homeRoute = require('./routes/home')
const signupRoute = require('./routes/signup')
const passport = require('passport')
const session = require('express-session')
const MongoStore = require('connect-mongo')
require('./db/connection')
require('./config/local-passport-setup')
require('./config/google-passport-setup')
const store = MongoStore.create({ mongoUrl: 'mongodb://localhost:27017/quora', collectionName: 'sessions' })
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.use(session({
resave: true,
saveUninitialized: true,
secret:'qwerty',
store: store,
cookie: {
maxAge: 24 * 60 * 60 * 1000
}
}))
app.use(passport.initialize())
app.use(passport.session())
app.set('view engine', 'hbs')
app.use('/', express.static(__dirname + '/public'));
app.get('/', (req, res) => {
if (!req.user) {
res.redirect('/login')
}
else {
res.redirect('/home')
}
})
app.use('/', homeRoute)
app.use('/login', loginRoute)
app.use('/auth', authRoute)
app.use('/', signupRoute)
app.listen(3000, () => {
console.log('server started on http://localhost:3000')
})
here I am calling the passport.authenticate function
onst express = require('express')
const route = express.Router()
const passport = require('passport')
require('../config/local-passport-setup')
route.get('/', (req, res) => {
res.render('login')
})
route.post('/', passport.authenticate('local', { successRedirect: '/home', failureRedirect: '/login' }))
module.exports = route
here the serialize user and deserialize user functions are never being called and thus the req.user is undefined
here the user is not getting authenticated although this oAuth code is working properly
const passport = require('passport')
const GoogleStrategy = require('passport-google-oauth20').Strategy
const GoogleUsers = require('../db/googleUser')
passport.use(new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: 'http://localhost:3000/auth/google/redirect'
},
(accessToken, refreshToken, profile, done) => {
GoogleUsers.findOne({ googleId: profile.id })
.then((currentUser) => {
if (currentUser) {
console.log('current user: ', currentUser)
done(null, currentUser)
}
else {
const newUser = new GoogleUsers({
googleId: profile.id,
name: profile.displayName
})
newUser.save()
.then((newUser) => {
console.log('new user: ', newUser)
done(null, newUser)
})
}
})
}
))
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(async (id, done) => {
await GoogleUsers.findById(id, function (err, user) {
done(err, user);
});
});
Please help me out I have been figuring out the error for a lot time now

ACL - Implement acl together with passport

I am trying out node_acl with passport-local. When I run my code I cannot secure the route for the admin-user '/admin' and I am redirected to the /login page.
Find below my minimum runnable example:
require('dotenv').config()
const express = require('express')
// const fs = require('fs')
const path = require('path')
const logger = require('morgan')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
const session = require('express-session')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const ACL = require('acl')
// load user.json file
// const d = fs.readFileSync(path.join(__dirname, '/../data/user.json'))
// const userObj = JSON.parse(d)
const userObj = [{
id: 1,
username: 'admin',
password: 'admin',
email: 'admin#admin.com',
role: 'admin',
},
{
id: 2,
username: 'user',
password: 'user',
email: 'user#user.com',
role: 'user',
},
]
const app = express()
// view engine setup
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'pug')
app.use(logger(process.env.LOG_ENV))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: false,
}))
app.use(express.static(path.join(__dirname, '/../public')))
app.use(cookieParser())
app.use(session({
secret: 'super-mega-hyper-secret',
resave: false,
saveUninitialized: false,
}))
/**
* Passport Local
*/
app.use(passport.initialize())
app.use(passport.session())
function authenticate() {
passport.serializeUser((user, done) => {
done(null, user.id)
})
passport.deserializeUser(async(id, done) => {
// const user = await serviceAuth.findById(id)
const user = userObj.find(item => item.id === id)
done(null, user)
})
// Sign in with username and Password
passport.use('local', new LocalStrategy({
usernameField: 'username',
}, async(username, password, done) => {
const user = userObj.find(item => item.username === username)
done(null, user)
}))
}
const isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
res.locals.user = req.session.user
return next()
}
res.redirect('login')
}
authenticate()
/**
* Node ACL
*/
function accessControl() {
const nodeAcl = new ACL(new ACL.memoryBackend())
nodeAcl.allow([{
roles: 'admin',
allows: [{
resources: '/admin',
permissions: '*',
}],
}, {
roles: 'user',
allows: [{
resources: '/dashboard',
permissions: 'get',
}],
}, {
roles: 'guest',
allows: [],
}])
// Inherit roles
// Every user is allowed to do what guests do
// Every admin is allowed to do what users do
nodeAcl.addRoleParents('user', 'guest')
nodeAcl.addRoleParents('admin', 'user')
nodeAcl.addUserRoles(1, 'admin')
nodeAcl.addUserRoles(2, 'user')
nodeAcl.addUserRoles(0, 'guest')
return nodeAcl
}
/*
function checkPermission(resource, action) {
const access = accessControl()
return (req, res, next) => {
const uid = req.session.user.id
access.isAllowed(uid, resource, action, (err, result) => {
if (result) {
next()
} else {
const checkError = new Error('User does not have permission to perform this action on this resource')
next(checkError)
}
})
}
} */
const getCurrentUserId = (req) => {
console.log(req)
req.user && req.user.id.toString() || false
}
const access = accessControl()
// Routes
app.get('/login', (req, res) => {
res.render('login')
})
app.post('/login', (req, res, next) => {
passport.authenticate('local', (err, user) => {
if (err) return next(err)
if (!user) {
return res.status(401).json({
error: 'Email or password is incorrect.',
})
}
return res.render('dashboard')
})(req, res, next)
})
app.get('/dashboard', [isAuthenticated, access.middleware()], (req, res) => {
res.render('dashboard')
})
app.get('/admin', [isAuthenticated, access.middleware()], (req, res) => {
res.render('admin')
})
app.get('/status', (request, response) => {
access.userRoles(getCurrentUserId(request), (error, roles) => {
response.send(`User: ${JSON.stringify(request.user)} Roles: ${JSON.stringify(roles)}`)
})
})
// Start Server
const port = process.env.APP_PORT || 8080
const host = process.env.APP_URL || 'localhost'
app.listen(port, host, () => {
console.log(`Listening on ${host}:${port}`)
})
module.exports = app
Any suggestions why the route, /admin cannot be called only be the admin user?
Thank you in advance for your replies!
I couldn't run your "runnable" code so i changed it a bit to check it out.
So after some tests it seems that it works just fine. Can you check it too?
Using POSTMAN I did a POST on /login?username=user&password=user
After that I did a GET on `/status' and I got
User: {"id":2,"username":"user","password":"user","email":"user#user.com","role":"user"} Roles: []
Then I did a GET on /admin and i got
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>HttpError: Insufficient permissions to access resource
<br> at C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\acl\lib\acl.js:705:14
<br> at tryCatcher (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\util.js:16:23)
<br> at Promise.successAdapter [as _fulfillmentHandler0] (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\nodeify.js:23:30)
<br> at Promise._settlePromise (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\promise.js:566:21)
<br> at Promise._settlePromise0 (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\promise.js:614:10)
<br> at Promise._settlePromises (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\promise.js:693:18)
<br> at Async._drainQueue (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\async.js:133:16)
<br> at Async._drainQueues (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\async.js:143:10)
<br> at Immediate.Async.drainQueues (C:\Users\stamoulis.zamanis\Desktop\aclTest\node_modules\bluebird\js\release\async.js:17:14)
<br> at runCallback (timers.js:789:20)
<br> at tryOnImmediate (timers.js:751:5)
<br> at processImmediate [as _immediateCallback] (timers.js:722:5)
</pre>
</body>
</html>
Then I logged in as admin and when I called /admin again i got admin
I had to change app.post('/login'). If i didnt do req.login then passport.serializeUser was never called, the cookie wasn't correct resulting in bad session.
app.post('/login', (req, res, next) => {
passport.authenticate('local', (err, user) => {
if (err) return next(err)
if (!user) {
return res.status(401).json({
error: 'Email or password is incorrect.',
})
}
req.logIn(user, function (err) { // <-- Log user in
next();
});
})(req, res, next)
},function(req,res){
res.send('dashboard')
})
All code:
require('dotenv').config()
const express = require('express')
// const fs = require('fs')
const path = require('path')
const logger = require('morgan')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
const session = require('express-session')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const ACL = require('acl')
// load user.json file
// const d = fs.readFileSync(path.join(__dirname, '/../data/user.json'))
// const userObj = JSON.parse(d)
const userObj = [{
id: 1,
username: 'admin',
password: 'admin',
email: 'admin#admin.com',
role: 'admin',
},
{
id: 2,
username: 'user',
password: 'user',
email: 'user#user.com',
role: 'user',
},
]
const app = express()
// view engine setup
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'pug')
app.use(logger(process.env.LOG_ENV))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: false,
}))
app.use(express.static(path.join(__dirname, '/../public')))
app.use(cookieParser())
app.use(session({
secret: 'super-mega-hyper-secret',
resave: false,
saveUninitialized: false,
}))
function authenticate() {
passport.serializeUser((user, done) => {
done(null, user.id)
})
passport.deserializeUser((id, done) => {
// const user = await serviceAuth.findById(id)
const user = userObj.find(item => item.id === id)
done(null, user)
})
// Sign in with username and Password
passport.use('local', new LocalStrategy({
usernameField : 'username',
passwordField : 'password'
}, async(username, password, done) => {
const user = userObj.find(item => item.username === username)
done(null, user)
}))
}
const isAuthenticated = (req, res, next) => {
if (req.isAuthenticated()) {
res.locals.user = req.session.user
return next()
}
res.redirect('login')
}
authenticate()
/**
* Passport Local
*/
app.use(passport.initialize())
app.use(passport.session())
/**
* Node ACL
*/
function accessControl() {
const nodeAcl = new ACL(new ACL.memoryBackend())
nodeAcl.allow([{
roles: 'admin',
allows: [{
resources: '/admin',
permissions: '*',
}],
}, {
roles: 'user',
allows: [{
resources: '/dashboard',
permissions: 'get',
}],
}, {
roles: 'guest',
allows: [],
}])
// Inherit roles
// Every user is allowed to do what guests do
// Every admin is allowed to do what users do
nodeAcl.addRoleParents('user', 'guest')
nodeAcl.addRoleParents('admin', 'user')
nodeAcl.addUserRoles(1, 'admin')
nodeAcl.addUserRoles(2, 'user')
nodeAcl.addUserRoles(0, 'guest')
return nodeAcl
}
/*
function checkPermission(resource, action) {
const access = accessControl()
return (req, res, next) => {
const uid = req.session.user.id
access.isAllowed(uid, resource, action, (err, result) => {
if (result) {
next()
} else {
const checkError = new Error('User does not have permission to perform this action on this resource')
next(checkError)
}
})
}
} */
const getCurrentUserId = (req) => {
console.log(req)
req.user && req.user.id.toString() || false
}
const access = accessControl()
// Routes
app.get('/login', (req, res) => {
res.send('login')
})
app.post('/login', (req, res, next) => {
passport.authenticate('local', (err, user) => {
if (err) return next(err)
if (!user) {
return res.status(401).json({
error: 'Email or password is incorrect.',
})
}
req.logIn(user, function (err) { // <-- Log user in
next();
});
})(req, res, next)
},function(req,res){
res.send('dashboard')
})
app.get('/dashboard', [isAuthenticated, access.middleware()], (req, res) => {
res.send('dashboard')
})
app.get('/admin', [isAuthenticated, access.middleware()], (req, res) => {
res.send('admin')
})
app.get('/status', (request, response) => {
access.userRoles(getCurrentUserId(request), (error, roles) => {
response.send(`User: ${JSON.stringify(request.user)} Roles: ${JSON.stringify(roles)}`)
})
})
// Start Server
const port = process.env.APP_PORT || 3335
const host = process.env.APP_URL || 'localhost'
app.listen(port, host, () => {
console.log(`Listening on ${host}:${port}`)
})
module.exports = app

Categories