Express.js:Passport.ensureAuthenticated()始终为真

时间:2018-12-09 22:12:14

标签: javascript node.js express passport.js

我对以下情况有些困惑。我正在使用带有Google Auth的护照JS登录我的网站。之后,我尝试确保登录后的路由安全,并且始终返回true。

我知道这是很多代码,我要花很多时间让别人检查一下,但是我真的很茫然,我想我错过了一些很明显的:(

谢谢您的宝贵时间!

这是相关的代码服务器index.js代码。我认为没有什么不寻常的

const env = process.env.NODE_ENV || 'development';
import dotenv from 'dotenv';
if (env === 'development') dotenv.config();

import express from 'express';
import bodyParser from 'body-parser';
import compression from 'compression';
import cookieParser from 'cookie-parser';
import methodOverride from 'method-override';

// IMPORT AUTH DEFAULT FUNCTION, THIS DEFINES THE STRATEGY
import auth from './middleware/auth';

import routes from './routes';
import database from './database';
import models from './models';

const PORT = process.env.PORT || 3000,
      app  = express(),
      router = express.Router(),
      sequelize = database();

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(compression());
app.use(cookieParser());
app.use(methodOverride());

models(sequelize).then(models => {
  // CALL AUTH DEFAULT FUNCTION, THIS SHOULD SET WHOLE STORY IN MOTION
  auth(app);
  routes(app);
  app.listen(PORT);
});

这是我的路由文件,我在声明路由器,最后说该应用程序应该使用它,实际上我怀疑这可能是问题所在,但不确定如何正确测试(除非我抛弃路由器并仅使用app.use代替router.use

import express from 'express';
import path from 'path';
import serveStatic from 'serve-static';

// IMPORT JUST THE ensureAuthenticated MIDDLEWARE
import {ensureAuthenticated} from '../middleware/auth';
import * as tasks from './tasks';

const router = express.Router(),
      root   = path.join(__dirname, '..');

export default function (app) {
  const frontendPublicPath = path.join(root, '..', 'frontend', 'build');

  router.use('/', serveStatic(frontendPublicPath));

  // TRY TO LOCK THIS ROUTE BEHIND AUTH
  router.use('/admin/dosomething', ensureAuthenticated, task.doSomething);

  router.use('*', serveStatic(frontendPublicPath));
  app.use('/', router);
};

最后是用于设置所有内容的身份验证文件

import passport from 'passport';
import expressSession from 'express-session';
import connectPgSimple from 'connect-pg-simple';
import googleAuth from 'passport-google-oauth';

import {models} from '../models/index';

const googleStrategy = googleAuth.OAuth2Strategy;

function setupPassport() {
  passport.serializeUser((user, done) => {done(null, user);});
  passport.deserializeUser((obj, done) => {done(null, obj);});

  passport.use(new googleStrategy({ clientID: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, callbackURL:  process.env.GOOGLE_CALLBACK_URL
    }, function (accessToken, refreshToken, profile, done) {
      process.nextTick(() => {
        models.Users.login(profile).then((userRecord) => {
          if (!userRecord.err) return done(null, userRecord);
          else return done(userRecord.err, null);
        });
      });
    }
  ));
}


/* Should be able to use this on whole app level if wanted, in that case
   allowedGuestRoutes would kick in to allow certain routes always to pass
   In example: app.use(ensureAuthenticated) !! NOT USED IN THIS CASE

   Also can be used on single routes by passing it as middleware
   In example: router.use('/admin/dosomething', 
                          ensureAuthenticated, 
                          task.doSomething);

   'root' route  - should be able to access route to get homepage served
   'dist' folder - should be able to access css / js and assets
   'auth' routes - should be able to access route to be able to login */

export function ensureAuthenticated(req, res, next) {
  const allowedGuestRoutes = ['/auth/','/api/'];
  if (req.isAuthenticated()) {
    // I ALWAYS END UP HERE SINCE THIS IF CASE IS ALWAYS TRUE <-----------
    return next();
  } else {
    /* Don't reject, check if this route is public */
    let publicRoute = false;
    if (req.url === '/') {
      publicRoute = true;
      return next();
    }
    allowedGuestRoutes.forEach(guestRoute => {
      if (req.url.indexOf(guestRoute) === 0) {
        publicRoute = true;
        return next();
      }
    });
    if (!publicRoute) {
      logger.error(req, 'Not allowed to access route');
      res.redirect('/');
    }
  }
}

export default function (app) {
  const pgSession       = connectPgSimple(expressSession),
        cookieAge       = 7 * 24 * 60 * 60 * 1000,
        sessionSettings = { 
          store: new pgSession({conString: process.env.DATABASE_URL,tableName: 'Sessions'}),
          secret: process.env.DATABASE_SECRET,
          resave: false,
          saveUninitialized: false,
          cookie: {maxAge: cookieAge}
        };

  app.use(expressSession(sessionSettings));
  setupPassport();
  app.use(passport.initialize());
  app.use(passport.session());
  //app.use(ensureAuthenticated);

  app.get('/auth/google', passport.authenticate('google', {scope: ['https://www.googleapis.com/auth/userinfo.email']}), (req, res) => {
    // this is being handled by google guys, they are smarter
  });

  app.use('/auth/google/callback', passport.authenticate('google', {failureRedirect: '/'}), (req, res) => {
    res.locals.user = req.user;
    if (req.cookies.loggedIn === undefined) {
      res.cookie('loggedIn', true, {maxAge: cookieAge});
    }
    res.redirect('/');
  });

  // on each request, save user data in res.local so we can use it on views
  app.use((req, res, next) => {
    if (!req.user) {
      req.user = {};
    }
    res.locals.user = req.user;
    next();
  });

  app.get('/logout', (req, res) => {
    if (req.user) {
      logger.action(req.user.name + ' logged out', 'gray');
    }
    req.logout();
    res.cookie('loggedIn', '', {expires: new Date(0)});
    res.redirect('/');
  });
};

回顾:

  • 问题auth.jsreq.isAuthenticated()始终设置为true。
  • frontend使用document.cookie.indexOf('loggedIn=') === -1;来确定是否需要在导航栏中显示登录或注销按钮,按预期工作
  • 如果我注销然后再次登录,将显示google窗口以选择用户(或使用google用户登录),因此这也可以正常使用

因此,最后唯一真正失败的是req.isAuthenticated()无法确定用户已注销。任何帮助或指针将不胜感激!

0 个答案:

没有答案