W
W
wlms2019-03-09 22:53:54
Node.js
wlms, 2019-03-09 22:53:54

PassportJS authentication server validation?

app.js // back
const config = require('./config');
const spdy = require('spdy');
const express = require('express');
const cors = require('cors')
const bodyParser = require('body-parser');
const VKontakteStrategy = require('passport-vkontakte').Strategy;
const passport = require('passport');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
const app = express();
app.use(cors());
app.use((req, res, next) => {
  res.set({
    'Access-Control-Allow-Origin': 'http://localhost:8080',
    'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, PATCH, DELETE',
    'Access-Control-Allow-Headers': 'X-Requested-With,content-type',
    'Access-Control-Allow-Credentials': true
  })
  next();
});

// DATABASE
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

mongoose.connection
    .on('error', error => console.log(error))
    .on('close', () => console.log('Database connection closed.'))
    .once('open', () => {
        const info = mongoose.connections[0];
        console.log(`Connected to ${info.host}:${info.port}/${info.name}`);
    });

mongoose.connect(config.MONGO_URL);

app.use(require('cookie-parser')());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(
  session({
    secret: 'secret',
    resave: true,
    saveUninitialized: false,
    store: new MongoStore({
      mongooseConnection: mongoose.connection
    }),
    cookie: {
      maxAge: 24 * 60 * 60 * 1000
    }
  })
);
app.use(passport.initialize());
app.use(passport.session());

const User = require('./api/models').User

passport.use(new VKontakteStrategy(
    {
      clientID:     'xxx', // VK.com docs call it 'API ID', 'app_id', 'api_id', 'client_id' or 'apiId'
      clientSecret: 'xxx',
      callbackURL:  "http://localhost:3001/auth/vkontakte/callback"
    },
    function myVerifyCallbackFn(accessToken, refreshToken, params, profile, done) {
      console.log(profile)
      User.findOne({
        vkontakteId: profile.id
      }, (err, user) => {
        if (err) {
          return done(err);
        }
        if (!user) {
          user = new User ({
            vkontakteId: profile.id,
            displayName: profile.displayName,
            photoUrl: profile.photos[0].value
          });
          user.save(() => {
            if (err) console.log(err);
            return done(null, user);
          })
        } else {
            return done(err, user);
        }
      })
    }
));

// User session support for our hypothetical `user` objects.
passport.serializeUser((user, done) => {
  done(null, user);
});

passport.deserializeUser((user, done) => {
  done(null, user);
});

//This function will pass callback, scope and request new token
app.get('/auth/vkontakte', passport.authenticate('vkontakte'));

app.get('/auth/vkontakte/callback',
  passport.authenticate('vkontakte', {
    successRedirect: 'http://localhost:8080/dashboard',
    failureRedirect: 'http://localhost:8080/auth' 
  })
);


app.get('/', function(req, res) {
  const user = req.user
  
  if(user){
    res.json({
      user: user
    });
  } else {
    res.json({
      message: 'Пользователь не аутентифицирован'
    })
  }
});

const loggedin = (req, res, next) => req.isAuthenticated() ? next() : res.json('Not Auth')
// // ROUTERS
const routes = require('./api/routes');
app.use('/api', loggedin, routes.profile);

app.listen(3001, () => {
    console.log('app listen port 3000')
})

module.exports = app;

auth.js // front vuex
import Axios from 'axios'

const state = {
  user: null
}

const actions = {
  authVkontakte: async ({commit}) => {
    const {data} = await Axios.get('http://localhost:3001/', {
      withCredentials: true
    })

    commit('authVkontakte', data.user)
  }
}

const mutations = {
  authVkontakte: (state, payload) => {
    state.user = payload
  }
}

const getters = {
  getUser: state => {
    return state.user
  }
}

export default {
  state,
  getters,
  actions,
  mutations
}

profiles.js // front view
import Axios from 'axios'

const state = {
  profiles: [],
}

const actions = {
  loadProfiles: async ({commit}) => {
    commit('clearError')
    commit('setLoading', true)
    try {
      const {data} = await Axios.get('http://127.0.0.1:3001/api/profiles/', {
        withCredentials: true
      })
      console.log(data)
      commit('loadProfiles', data.profiles)
      commit('setLoading', false)
    } catch (error) {
      commit('setLoading', false)
      commit('setError', error.message)
      throw error
    }
  }
}

const mutations = {
  loadProfiles: (state, payload) => {
    state.profiles = payload
  }
}

const getters = {
  getProfiles: state => {
    return state.profiles
  }
}

export default {
  state,
  getters,
  actions,
  mutations
}


Issue: When checking loggedin in a route, routes.profile returns false. (Perhaps it's asynchrony). After creating the view, the user is not authenticated for some time. And most likely at this time there is a check for loggedin -> and gives out false
It is possible that, in principle, the authentication logic is violated. But the user returns from the session and logs out if the session is deleted from the database. It is necessary that req.user
be available in the routes and, accordingly, loggedin produces true

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question