简体   繁体   中英

req.isAuthenticated() in express and passport-local returns false

I hope someone can shed some light on my situation. The req.isAuthenticated() always returns false, after being called in an app.router endpoint( running in port 3001 ), via fetch API. It appears, the connect.sid was not successfully passed on req arg when I do req.isAuthenticated()

On the other hand, my react dev server runs on port 3000

Here is my current setup.

Login Route, which authenticates username and password, and returns connect.sid via cookie value.

const express           = require('express')
const router            = express.Router()
const passport          = require('passport')
...
router.post( '/authenticate', passport.authenticate('local'), ( req, res, next ) => {
    res.status( 200 ).json({
        'response': 'Welcome User',
        'redirect' : '/dashboard'
    })
})
...
module.exports = router

At this point, my Users Route should be able to access the protected route. which simply returns all users on the database.

const express           = require('express')
const router            = express.Router()
const SimpleCmsUsers    = require('../models/Users.models.js')
const authPassportLocal = require('../passport/auth.PassportLocal.js') 
...
router.get( '/', authPassportLocal ,( req, res, next ) => {
    console.log( req.headers )
    console.log( req.body )

    SimpleCmsUsers
    .find({})
    .then(( users ) => {
        return res.status( 200 ).json( users )
    })
    .catch(( error ) => {
        return res.status( 403 ).json( error )
    })
})
...
module.exports = router

My auth.PassportLocal.js which checks the value of req.isAuthenticated()

const authPassportLocal = ( req, res, next ) => {
    console.log( req.headers ) // I do not see session has been passed on my request
    console.log( req.body )    // empty
    console.log('isAuthenticated', req.isAuthenticated() ) // log if isAuthenticated returns true. 
    if ( req.isAuthenticated() ) {
         return next()
    }
    return res.redirect('/dashboard/login/index')
}
....
module.exports = authPassportLocal

Now, when I call /dashboard/users the via fetch API

fetch( '/dashboard/users', {
    headers :{
        'Content-Type' : 'application/x-www-form-urlencoded'
    },
    credentials: 'include',
})
.then(( response ) => response.json())
.then(( users ) => console.log( users ))
.catch(( error ) => console.log( error ))

this returns isAuthenticated false , I tried to view the headers received from, /dashboard/users , however, I do not see any cookies passed on my request.

Here is my index.js

const express           = require('express')
const session           = require('express-session')
const flash             = require('express-flash')
const cors              = require('cors')
const passport          = require('passport')
const LocalStrategy     = require('passport-local').Strategy
const Users             = require('./routes/Users.routes.js')
const Login             = require('./routes/Login.routes')
const SimpleCmsUsers    = require('./models/Users.models.js')
const app               = express()

app.use( express.json() )
app.use( express.urlencoded({ extended: true }) )
app.use( cors({
     origin: ['http://localhost:3001', 'http://localhost:3000'],
     credentials: true
}))
app.use( flash() )
app.use( session({
    secret: 'EUE7J3lUE01xhmCGQt04S8PbsMpUE5JDcQj0fyS0cy73PQVDLM',       
    resave: true,
    saveUninitialized: true
}))
app.use( passport.initialize() )
app.use( passport.session() )

passport.use( new LocalStrategy(
    {
        // passport-local option here ...
    },
    ( username, password, done ) => {
        try {
            SimpleCmsUsers.find({ user_username : username, user_password : password }, function ( err, docs ) {
                if ( !docs.length ) {
                    return done( null, false, { message: "User not found!" } )
                }
                return done( null, username )
            })
        }
        catch( error ) {
            return done( null, false, { message: error } )
        }
    }
))
passport.serializeUser(function( user, done ) {
    done( null, user );
})
passport.deserializeUser(function( user, done ) {
    done( null, user );
})

app.use('/dashboard/users', Users)
app.use('/dashboard/login', Login)

app.listen( PORT, () => console.log("Express JS is on port " + PORT) )

What bothers me most, these current setup works on Postman without this type of challenge.

In my fetch API request ( http://localhost:3001/dashboard/users '):

url /
headers {
  host: 'localhost:3001',
  connection: 'keep-alive',
  pragma: 'no-cache',
  'cache-control': 'no-cache',
  'sec-fetch-dest': 'empty',
  'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36',
  dnt: '1',
  'content-type': 'application/x-www-form-urlencoded',
  accept: '*/*',
  origin: 'http://localhost:3000',
  'sec-fetch-site': 'same-site',
  'sec-fetch-mode': 'cors',
  referer: 'http://localhost:3000/dashboard/users',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'en-US,en;q=0.9,fil;q=0.8',
  cookie: 'connect.sid=s%3AJEG3MNSqtl33KqmHR2DhGlslnlkMKIPT.xsI%2F%2B82%2F1x8zTlq%2BkRN6aJVVbrauH8qv8jDhsrvNlbY'
}
body {}
user undefined
session Session {
  cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true }
}
isAuthenticated false

In Postman ( http://localhost:3001/dashboard/users '):

url /
headers {
  'content-type': 'application/x-www-form-urlencoded',
  'user-agent': 'PostmanRuntime/7.22.0',
  accept: '*/*',
  'cache-control': 'no-cache',
  'postman-token': '443a064e-7909-43db-9783-79a6ba8bd4c5',
  host: 'localhost:3001',
  'accept-encoding': 'gzip, deflate, br',
  cookie: 'connect.sid=s%3AsvbYi_oxm4yqXTTa7S-N-3qAT6BdW5-u.QYFAXzayArpV1%2BDbjnwJ3fMMjpLzkM%2Fr9kIUCUCYscY',
  connection: 'keep-alive'
}
body {}
user username
session Session {
  cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true },
  passport: { user: 'username' }
}
isAuthenticated true

It just I can not see what went wrong, why fetch API cannot pass the cookie value from connect.sid

Any help or guide where to isolate this behavior better are highly appreciated.

TA

Update

npm run start // for react dev server running in port 3000
nodemon api/v1/index.js // for express api running in port 3001

Tried these threads below, however, I do not see any progress on my end:

passport's req.isAuthenticated always returning false, even when I hardcode done(null, true)

Basics of Passport Session (expressjs)-why do we need to serialize and deserialize?

Your code is correct.

Only question is that how cookies being set.

Since You're backend runs at :3001 cookies being set as for host: localhost:3001 .

Read this issue: https://github.com/jaredhanson/passport/issues/403

solution is to make session middleware to set cookie by different host

app.use( session({
    secret: 'EUE7J3lUE01xhmCGQt04S8PbsMpUE5JDcQj0fyS0cy73PQVDLM',       
    resave: true,
    saveUninitialized: true,
    cookie: {domain: 'localhost:3000'}
}))

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