简体   繁体   中英

isAuthenticated() in Passport js always return false

I have been browsing the forum but I am unable to find the error in my code , it always results in false and I am not able to solve it , Please help me... Is there any other way to authenticate user instead of passport so that I can use it.I am adding more sentences as it is not allowing me to post my query,Sorry..

 const http = require("http"), hostname = "127.0.0.1", port = 3000, bodyParser = require("body-parser"), mongoose = require("mongoose"), express = require("express"), passport = require("passport"), localStrategy = require("passport-local"), passportLocalMongoose = require("passport-local-mongoose"), User = require("./models/user"); app = express(); mongoose.connect("mongodb://localhost/drive", { useNewUrlParser: true }); app.set("view engine", "ejs"); app.use(express.static("public")); app.use(passport.initialize()); app.use(passport.session()); app.use( require("express-session")({ secret: "Beta tumse na ho payega", resave: false, saveUninitialized: false }) ); passport.use(new localStrategy(User.authenticate())); passport.serializeUser(User.serializeUser()); passport.deserializeUser(User.deserializeUser()); app.use(bodyParser.urlencoded({ extended: true })); const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader("Content-Type", "text/plain"); }); app.get("/", function(req, res) { res.render("index"); }); app.get("/register", function(req, res) { res.send("hello"); }); app.get("/login", function(req, res) { res.render("login"); }); app.post( "/login", passport.authenticate("local", { successRedirect: "/", failureRedirect: "/login" }), function(req, res) {} ); app.get("/logout", function(req, res) { req.logout(); res.redirect("/"); }); function isLoggedIn(req, res, next) { if (req.isAuthenticated()) { return next(); } else { console.log("Not logged"); res.redirect("/login"); } } app.get("/secret", isLoggedIn, function(req, res) { res.send("You are logged in"); }); app.post("/register", function(req, res) { if (req.body.password === req.body.cpassword) { User.register( new User({ username: req.body.username }), req.body.password, function(err, user) { if (err) console.log(err); else passport.authenticate("local")(req, res, function() { res.send("signed up"); }); } ); } else res.send("Password Mismatch"); }); //DRIVE SCHEMA //var driveSchema = mongoose.Schema({ // title: String, // created: { type: Date, default: Date.now } //}); app.listen(port, hostname, function() { console.log("Server is running at " + hostname + "/" + port); }); 

 //./models/user.js file const mongoose = require("mongoose"), passportLocalMongoose = require("passport-local-mongoose"); var UserSchema = new mongoose.Schema({ username: String, password: String }); UserSchema.plugin(passportLocalMongoose); module.exports = mongoose.model("User", UserSchema); 

I have used passport and jwt library, to authenticate and maintain session for the user. There is no need to maintain user session on server side.

apis/apis.js : This file has all apis end points. /login url will authenticate user using passport and send a token to the client using jwt

const passport = require('passport')
const expRoute = require('express').Router();
let exporter = process.exporter;
expRoute.post('/login', (req, res, next) => {
  passport.authenticate(
    'local', 
    { 
        // successRedirect: '/',
        // failureRedirect: '/login',
        successFlash: 'Welcome!',
        failureFlash: 'Invalid username or password.' 
    },
    (err, user, info) => {
        if (err) {
            return res.status(500).json(err)
        }
        else if (user) {
            return res.status(200).json({
                token: exporter.generateToken(user)
            })
        }
        else {
            return res.status(400).json(info)
        }
    }
  )(req, res, next);
})
expRoute.get('/view', exporter.authenticateToken, (req, res) => {
    let param = req.finalTokenExtractedData
    if (param && exporter.isObjectValid(param, 'tokenId', true, true)) {
        let condition = {
            _id: param.tokenId
        }
        let options = {
            _id: 0,
            password: 0,
            __v: 0
        }
        process.USER.findOne(condition, options) // mongo find
        .then((data) => {
            res.status(200).json({
                 result: data,
                 msg: 'success'
            })
        })
       .catch((mongoErr) => {
            exporter.logNow(`USER mongo Error: ${mongoErr}`)
            res.status(400).json({
                msg: 'user not found'
            })
        })
    }
    else {
        res.status(404).json({
            msg: 'invalid token'
        })
    }
})
module.exports = expRoute

common/env.js: This file will initialise all connections such mongo, require few files will be used as global

process.CONFIG = require('../configs/config.json')

process.exporter = require("../lib/exporter.js")

process.dbInit = (globalName, mongoUrl, collectionName) => {
    require("../models/db-init.js")(mongoUrl, collectionName)
    .then((modelObj) => {
        process[globalName] = modelObj // will be used as global
    })
    .catch((dbInitErr) => {
        process.exporter.logNow(`dbInit Error: ${dbInitErr}`)
        process.exit()
    });
}

lib/exporter.js: This file has exporter class which consist of all major functions like mongo connection, authenticateToken, verifyPassword, etc.

const fs = require('fs'),
    redis = require("redis"),
    path = require("path"),
    mongoose = require('mongoose'); mongoose.set('useCreateIndex', true);
const Schema = mongoose.Schema;
var bcrypt = require('bcryptjs')
var jwt = require('jsonwebtoken')

class Exporter  {
    mongoConnection(mongoURI, schemaObj) {
        return new Promise(async (resolve, reject) => {
            if (!mongoURI || typeof mongoURI == 'undefined' || mongoURI.length < 1)
                return reject('invalid mongo connection url');
            return resolve(mongoose.createConnection(mongoURI, { useNewUrlParser: true }))
        })
    }
    createMongoSchema(schemaObj) {
        return (new Schema(schemaObj));
    }
    createMongoModel(mongoDB, collectionName, newSchema) {
        if (newSchema)
            return mongoDB.model(collectionName, newSchema)        
        return mongoDB.model(collectionName)
    }
    authenticateToken(req, res, next) {
        const bearerHeader = req.header('authorization')
        if (typeof bearerHeader != 'undefined') {
            const bearer = bearerHeader.split(' ')
            const bearerToken = bearer[1] 
            jwt.verify(bearerToken, process.CONFIG.jwt.token.activated, (err, data) => {
                if (err)
                    res.status(400).json({
                        msg: "Invalid token or please try to login again"
                    })
                else {
                    process.exporter.getSingleHashKeysValuesFromRedis('expired_token', bearerToken)
                    .then((redisTokendata) => {
                        if (redisTokendata)
                            res.status(400).json({
                                msg: "token expired"
                            })
                        else {
                            req.finalTokenExtractedData = data
                            // if (req.originalUrl.trim() == process.logoutURL.trim())
                                req.jwtToken = {
                                    token: bearerToken,
                                    secret: process.CONFIG.jwt.token.activated
                                }
                            next()
                        }
                    })
                    .catch((redisTokenError) => {
                        process.exporter.logNow(`redis token error: ${redisTokenError}`)
                        res.status(400).json({
                            msg: "Some went wrong while checking token. Please try later."
                        })
                    })
                }
            })
        }
        else 
            res.status(400).json({
                msg: "invalid token"
            })
    }
    generateToken(data) {
        let expiry = new Date();
        // expiry.setDate(expiry.getDate() + 7)
        expiry.setMinutes(expiry.getMinutes() + 5)
        return jwt.sign({
            tokenId: data._id,
            exp: parseInt(expiry.getTime() / 1000),
        }, process.CONFIG.jwt.token.activated)
    }    
    createPassword(password) {
        return new Promise((resolve, reject) => {
            if (typeof password == 'undefined' && password == '')
                return reject('password empty')
            bcrypt.hash(password, 10, async (bErr, hash) => {
                if (bErr)
                    reject(bErr)
                else
                    resolve(hash)
            })
        })
    }
    verifyPassword(enteredPassword, savePassword) {
        return bcrypt.compareSync(enteredPassword, savePassword)
    }
}
module.exports = (new Exporter());

index.js: This is file which you will execute node index.js .

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const passport = require('passport');

require('./common/env')
require('./configs/passport')

const app = express()

const cors = require('cors')
app.use(cors());
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true}))
app.use(passport.initialize())

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

let apis = require('./apis/api')
app.use('/user', apis)

/**
 * 404 Handler
 */
app.use((req, res, next)=>{
    return res.status(404).send("Endpoint "+req.url +" not found");
})

/**
 * if any error or exception occurred then write into a JS file so that app can be restarted
 */
process.on('uncaughtException', (err) => {
    console.error(err.stack);
});


app.listen(3000, function(server) {
    console.log("App listening at 3000");
});

When index.js file has been executed successfully and listening to a port 3000, then use this URL http://localhost:3000/user/login for authentication, it will accept your username and password, then authenticate using passport and send a token to the client as response. The token can contain user data in encrypted form and have expiry time.

Reference link: https://github.com/arjun-707/login-logout-jwt-nodejs

You need the express-session module.

server.js

 // Require a possible config.js file with your configuration variables const Config = require('./models/config.js'); // If the config module is formed as a class const config = new Config(); const express = new('express'); const app = express(); const session = require('express-session'); const MongoStore = require('connect-mongo')(session); const uuid = require('uuid/v4'); const mongoose = require('mongoose'); // Require your custom passport local strategy file const passport = require('./models/sessions'); mongoose.connect('mongodb://localhost:27017/your_db_name', { useNewUrlParser: true }); // Set the session options app.use(session({ // Use UUIDs for session IDs genid: (req) => { return uuid() }, // If you want to store the session in MongoDB using mongoose // Require your personal mon store: new MongoStore({ mongooseConnection: mongoose.connection }), // Define the session secret in env variable or in config file secret: process.env.SESSION_SECRET || config.sessionSecretKey, resave: false, saveUninitialized: true })); // Initialize the passport module app.use(passport.initialize()); // Tell to passport to use session app.use(passport.session()); 

./models/session.js

 const passport = require('passport'); const LocalStrategy = require('passport-local').Strategy; const bcrypt = require('bcrypt-nodejs'); // Your custom MongoDB connection module const db = require('./db'); // Configure passport.js to use the local strategy passport.use(new LocalStrategy({ usernameField: 'username' }, (username, password, done) => { db.User.find({ username: username // But it could use email as well }).then(res => { const user = JSON.parse(JSON.stringify(res[0])); if (!user) { return done(null, false, { message: 'Invalid credentials.\\n' }); } if (!bcrypt.compareSync(password, user.password)) { return done(null, false, { message: 'Invalid credentials.\\n' }); } return done(null, user); }).catch(error => done(error)); } )); // Tell passport how to serialize the user passport.serializeUser((user, done) => { done(null, user._id); }); // Tell passport how to deserialize the user passport.deserializeUser((id, done) => { db.User.find({ _id: id }).then(res => { const response = typeof res !== undefined && res.length != 0 ? JSON.parse(JSON.stringify(res[0])) : null; done(null, response) }).catch(error => done(error, false)) }); // Export passport for external usage module.exports = passport; 

./models/db.js

 const mongoose = require('mongoose'); const Schema = mongoose.Schema; const uuid = require('uuid/v4'); // Connect to MongoDB mongoose.connect('mongodb://localhost:27017/your_db_name', { useNewUrlParser: true }); // Define the models container let models = {}; // Prepare your user schema const userSchema = Schema({ username: { type: String, required: true }, password: { type: String, required: true } }); // Assign the user schema models.User = mongoose.model('User', userSchema); // Export for external usage module.exports = models; /* In that way you can wrap in "models" all schemas: const newSchema = Schema({ name: String }); models.Newschema = mongoose.model('Newschema', newSchema); module.exports = models; And use it externally like: const db = require('./models/db'); db.User.find({}).then(docs => {}).catch(err => {}); db.Newschema.find({}).then(docs => {}).catch(err => {}); Etc.... */ 

./models/config.js

 class Config { constructor() { this.sessionSecretKey = "my-awesome-secretkey"; /* And other configurations */ } } module.exports = Config; /* Externally use like: const Config = require('./models/config'); const config = new Config(); let sessionSecretKey = config.sessionSecretKey; */ 

Then you can use the req.isAuthenticated() after the login:

 // POST the username and password to '/login' router app.post('/login', (req, res, next) => { passport.authenticate('local', (err, user, info) => { if (info) { return res.send(info.message) } if (err) { return next(err); } if (!user) { return res.sendStatus(404); // Is a shortcut // OR -> res.status(404).end(); // OR -> res.status(404).send('Not found'); as you like } req.login(user, (err) => { if (err) return next(err); // Store the user object retrieved from MongoDB in `req.session` req.session.user = user; return res.sendStatus(200); // Is a shortcut // OR -> res.status(200).end(); // OR -> res.status(200).send('OK'); as you like }) })(req, res, next); }); // The logout logic app.get('/logout', verifySession, function (req, res) { req.session.destroy(function (err) { req.logout(); res.redirect('/'); }); }); // Verify the session to protect private routers function verifySession(req, res, next) { if (req.isAuthenticated()) { next(); } else { // Forbidden res.redirect('/'); // OR -> res.sendStatus(403); // OR -> res.status(403).end(); // OR -> res.status(403).send('Forbidden'); as you like } } 

Of course you have to run npm install with all the dependencies required defined in package.json file or manually instal with npm i express-session@latest --s for all the dependencies required: npm i module-name@latest --s .

Don't forget the

const server = app.listen(config.port || 3000, () => {
    console.log(`Server running on ${server.address().port} port.`);
});

At the end of server.js file. I hope that it will be useful for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM