Express.js: Passport.ensureAuthenticated () всегда верно - PullRequest
0 голосов
/ 10 декабря 2018

Я немного запутался в следующей ситуации.Я использую паспорт JS с Google Auth для входа на мой сайт.После этого я попытался защитить маршрут за логином, и он всегда возвращает 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.jsчто req.isAuthenticated() всегда имеет значение true.
  • Фронтенд использует document.cookie.indexOf('loggedIn=') === -1;, чтобы выяснить, нужно ли показывать кнопку входа или выхода из системы в панели навигации, работает как ожидалось
  • , если я выйду из системы и затемзайдите снова, чтобы войти, мне будет представлено окно Google, чтобы выбратьuser (или войдите с помощью пользователя Google), так что это работает так же, как и ожидалось

Так что, в конце концов, единственное, что действительно терпит неудачу, это то, что req.isAuthenticated() не может понять, что пользователь вошел в системуиз.Любая помощь или указатели будут высоко оценены!

...