rkusa / koa-passport

Passport middleware for Koa
MIT License
774 stars 54 forks source link

passport.deserializeuser not called,and ctx.isAuthenticated() always equals false #100

Closed cheneyweb closed 5 years ago

cheneyweb commented 7 years ago
  1. The following is my key package "koa": "^2.2.0", "koa-passport": "^3.0.0", "koa-router": "^7.0.1", "koa-session": "^5.0.0"

  2. My problem is when I use "ctx.isAuthenticated()" to check if user login before, ctx.isAuthenticated() always equal false even user has login by passport.authenticate

3.The following is my code:

app.js

const session = require('koa-session')
const passport = require(__dirname + '/src/auth/passport_config.js')
const xauth = require('./src/auth/router_auth.js')

const app = new Koa()
app.proxy = true
app.keys = ['your-session-secret']
app.use(session(app))

app.use(bodyParser())

app.use(passport.initialize())
app.use(passport.session())
app.use(mount('/',xauth.routes()))

passport_config.js

const passport = require('koa-passport')
const LocalStrategy = require('passport-local')
const UserModel = require(__dirname + '/../../src/model/UserModel')

passport.use(new LocalStrategy(

    function(username, password, done) {
        UserModel.findOne({ username: username }).then(function(result) {
            if (result != null) {
                if (result.password == password) {
                    return done(null, result);
                } else {
                    log.error('密码错误');
                    return done(null, false, { message: '密码错误' })
                }
            } else {
                log.error('用户不存在');
                return done(null, false, { message: '用户不存在' })
            }
        }).catch(function(err) {
            log.error(err.message);
            return done(null, false, { message: err.message })
        });
    }
));

passport.serializeUser(function(user, done) {
    done(null, user);
});

passport.deserializeUser(function(user, done) {
    console.info(user)
    return done(null, user);
});

router_auth.js

const Router = require('koa-router')
const log = require('tracer').colorConsole({ level: require('config').get('log').level })
const router = new Router()
const passport = require(__dirname + '/passport_config.js')

router.post('/login', function(ctx, next) {
    return passport.authenticate('local', function(err, user, info, status) {
        if (user === false) {
            ctx.body = { success: false }
            ctx.throw(401)
        } else {
            ctx.body = { success: true }
            return ctx.login(user)
        }
    })(ctx, next)
})

router.post('/test', function(ctx, next) {
    if (ctx.isAuthenticated()) {
        console.info('认证通过')
        return next()
    } else {
        ctx.body = '非法访问'
    }
})

module.exports = router

I try http://localhost/login,it work But I try http://localhost/test,it doesn't work,it is always false,and passport.deserializeUser has never been called

I am very looking forward to your help,and sorry for my pool english

rkusa commented 7 years ago

Hm, I do not see an error, yet. Is passport.serializeUser being called?

rkusa commented 7 years ago

I've updated a koa-passport-example branch to be more closely to what you are doing and it is working fine. Would you mind checking whether https://github.com/rkusa/koa-passport-example/tree/issue_100 does work for you?

ghost commented 7 years ago

Temporarily use

export async function authenticatedUser(ctx: Router.IRouterContext, next: () => Promise<any>) {
    if (ctx.session.passport.user && ctx.session.passport.user.user) {
        ctx.state.user = ctx.session.passport.user.user;
        await next();
    } else {
        ctx.throw(401, 'authenticate please');
    }
}
rkusa commented 7 years ago

Are there any updates on this issue? @gyeongmin-ji thanks for the workaround. Do you have a similar issue, which requires this workaround?

jenkynolasco11 commented 6 years ago

I'm having the same issue, but my situation is a bit weird. This is my code:

import Router from 'koa-router'
import passport from 'koa-passport'
import { setUserData } from '../../utils'
import { User, Bus } from '../../../models'

const auth = new Router({ prefix : 'auth' })

const isAuthenticated = async (ctx, next) => {
  try {
    if(ctx.isAuthenticated()) {
      const { user } = ctx.state

      const data = await setUserData(user)

      return ctx.body = { ok : true, data : { userInfo : data }, message : '' }
    }
  } catch (e) {
    console.log(e)
  }

  return next()
}

auth.post('/login', isAuthenticated, ctx =>
  passport.authenticate('local', async (err, user, msg) => {
    const { driverToken } = ctx.request.body

    if(user) {
      await User.findByIdAndUpdate(user, { lastSession : Date.now() })
      await ctx.login(user)

      const data = await setUserData(user)

      return ctx.body = { ok : true, data : { userInfo : data }, message : '' }
    }

    ctx.status = 401 // unauthorized

    return ctx.body = { ok : false, data : null, message : msg }
  })(ctx)
)

auth.get('/check-auth', async ctx => {
  console.log(`User is ${ ctx.isAuthenticated() ? '' : 'not' } authenticated`)

  if(ctx.isAuthenticated()) {
    console.log('Inside, boys!')

    const data = await setUserData(ctx.state.user)

    return ctx.body = { ok : true, data : { userInfo : data }, message : '' }
  }

  return ctx.body = { ok : false, data : null, message : 'There is no saved session available' }
})

My situation is the following:

  1. I refresh the page, a request to /check-auth is made, and ctx.isAuthenticated() returns false (as expected)
  2. I log in, the session is stored and user logged. Nothing different.
  3. I log out, ctx.logout() is called.
  4. If I refresh the page, step 1 is made. Great, that's how's supposed to work, because I logged out. But if I reload while being logged in, /check-auth returns false.
  5. If I try to log in after logging out, ctx.isAuthenticated() returns true.

Not sure if this is a bug, or if this is supposed to work like this.

My setup: "koa": "next", "koa-passport": "^4.0.1" "koa-router": "^7.0.1" "koa-session": "^5.5.1"

Any idea why is this happening? Or something I could work around? I tried the solution up there and it didn't work (passport returning undefined in /check-auth, on ctx.session.passport)

Bonus: If I set to request /check-auth after being logging out, it also returns false (including returning undefined when checking on ctx.session.passport, but if I log back in, the object exists.

Also, when I try to log in in another browser (different user, different cookies), the object appears with only one user, not storing the one already logged in, but instead overwriting it.

peakman commented 6 years ago

I’m pretty sure that in the end I resolved it by changing the order in which packages were initialised.

This is the order that worked for me. At one time I had something different that worked with earlier versions but not the latest.

app.use(session(sessionOptions, app)); app.use(passport.initialize()) app.use(passport.session())

Hope it might help.

Steve

On 16 Jan 2018, at 22:49, Jenky W. Nolasco notifications@github.com wrote:

I'm having the same issue, but my situation is a bit weird. This is my code:

import Router from 'koa-router' import passport from 'koa-passport' import { setUserData } from '../../utils' import { User, Bus } from '../../../models'

const isAuthenticated = async (ctx, next) => { try { if(ctx.isAuthenticated()) { const { user } = ctx.state

  const data = await setUserData(user)

  return ctx.body = { ok : true, data : { userInfo : data }, message : '' }
}

} catch (e) { console.log(e) }

return next() }

auth.post('/login', isAuthenticated, ctx => passport.authenticate('local', async (err, user, msg) => { const { driverToken } = ctx.request.body

if(user) {
  await User.findByIdAndUpdate(user, { lastSession : Date.now() })
  await ctx.login(user)

  const data = await setUserData(user)

  return ctx.body = { ok : true, data : { userInfo : data }, message : '' }
}

ctx.status = 401 // unauthorized

return ctx.body = { ok : false, data : null, message : msg }

})(ctx) )

auth.get('/check-auth', async ctx => { console.log(User is ${ ctx.isAuthenticated() ? '' : 'not' } authenticated)

if(ctx.isAuthenticated()) { console.log('Inside, boys!')

const data = await setUserData(ctx.state.user)

return ctx.body = { ok : true, data : { userInfo : data }, message : '' }

}

return ctx.body = { ok : false, data : null, message : 'There is no saved session available' } }) My situation is the following:

I refresh the page, a request to /check-auth is made, and ctx.isAuthenticated() returns false (as expected) I log in, the session is stored and user logged. Nothing different. I log out, ctx.logout() is called. If I refresh the page, step 1 is made. Great, that's how's supposed to work, because I logged out. But if I reload while being logged in, /check-auth returns false. If I try to log in after logging out, ctx.isAuthenticated() returns true. Not sure if this is a bug, or if this is supposed to work like this.

My setup: "koa": "next", "koa-passport": "^4.0.1" "koa-router": "^7.0.1" "koa-session": "^5.5.1"

Any idea why is this happening? Or something I could work around? I tried the solution up there and it didn't work (passport returning undefined in /check-auth, on ctx.session.passport)

Bonus: If I set to request /check-auth after being logging out, it also returns false (including returning undefined when checking on ctx.session.passport, but if I log back in, the object exists.

Also, when I try to log in in another browser (different user, different cookies), the object appears with only one user, not storing the one already logged in, but instead overwriting it.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rkusa/koa-passport/issues/100#issuecomment-358134134, or mute the thread https://github.com/notifications/unsubscribe-auth/AB0yhUFvYAbF-wFv8Os-I6YweXfCMHy5ks5tLSd7gaJpZM4NTgWo.

SkeLLLa commented 6 years ago

Got the same problem, however latest solution doesn't work for me, I already have such order, but it still doesn't call deserialize method. However ctx.session is populated with correct session.

It seems this module is absolutely incompatible with koa-session when external session storage is used.

rkusa commented 5 years ago

It seems this module is absolutely incompatible with koa-session when external session storage is used.

Looks like it, as also mentioned in other issues. If someone is going to provide a bare minimum app with this failing setup, I am willing to investigate. Other than that, there are other session middlewares out there that seem to work fine with an external session store.