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());
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.
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'}))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With