Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js, Vue.js and Passport.js. .isAuthenticated() always returns false? Axios headers possibly?

I'm moving a project over to Vue.js and I can't get any of my middleware to check if users are logged in or to check user ownership of things to work. After searching endlessly, I believe that the problem is that the headers I send from my client to server don't contain the passport serialized user or something? How can I make this work?

Here is my login route on the back-end:

      router.post("/login", function (req, res, next) {
    if (!req.body.username || !req.body.password) {
      res.send("Error");
    } else if(req.body.username.length > 40 || req.body.password.length > 40){
      res.send("Error");
    } else if (req.body.username) {
      req.body.username = req.body.username.toLowerCase();
      next();
    }
  }, passport.authenticate('local', {
    failureRedirect: '/login'
  }), function(req, res){
        User.findById(req.user.id, function(err, user){
          if(err){
            res.send("User not found");
          } else {
            res.send(user.toJSON());
          }
        })
  });

Here is my login page on the client side:

          async login () {
          const response = await AuthenticationService.login({
                username: this.username,
                password: this.password,
            })
            if(response.data == "Error"){
                this.$router.push({
                    name: 'login'
                })
            } else {
            this.$store.dispatch('setUser', response.data._id);
            this.$router.push({
                name: 'home'
            })
            }
        }

Here is the axios call that AuthenticationService.login is referencing:

    login(credentials){
    return Api().post('login', credentials);
},

Api comes from:

import axios from 'axios';

 export default function(){
   return axios.create({
      baseURL: `http://localhost:8081/`
   });
  }

So how do I make the front-end send the right headers to the back-end after a user is authenticated? As you can see, I store the user id in a vuex state, but I don't think that would be safe to use to confirm ownership and whether or not users are logged in, right? Or would it? I could easily just send that over in the requests, is that right? I feel like that's not safe enough, but Idk what I'm talking about.

EDIT: Here is the passport setup in app.js

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use(flash());
app.use(cookieParser());

app.use(express.session({ //5a6ba876578447262893ac69
    secret: "sessionSecret",
    resave: false,
    saveUninitialized: false
  }));
app.locals.moment = require('moment');
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
like image 464
Setheroni Avatar asked Jul 28 '18 00:07

Setheroni


2 Answers

Your issue is because your frontend and backend are on different domains.

Cookies, which passport.session()/express.session() use to maintain a user session, are scoped to a specific domain.

When you call axios.get() on the protected resource, axios will not send or receive cookies because localhost:8080 is a different domain to localhost:8081.

Try axios.get('/path/to/your/resource', { withCredentials: true }) and axios.post('/login', { username, password }, { withCredentials: true })

This would have been present even without Vue so long as you're using AJAX to make these calls.

like image 69
Dan Avatar answered Oct 22 '22 02:10

Dan


requests.js

let axiosConfig = {
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': 'http://localhost:3000/',
    'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE'
  }
}

server.js

var express  = require('express');
var app      = express();
var cors = require('cors');
app.use(cors({credentials: true, origin: 'http://localhost:8080'}))

app.use(cors({credentials: true, origin: 'http://localhost:8080'}))