I tried to get a value from express session (req.session.userid) in Nuxt by this.$session.userid, but I couldn't get the value in console.log.
It just showed "Cannot read properties of undefined (reading 'userid')"
If I get the value of this.$session then it just showed 'undefined'
If I want to get the value through the session normally, then how I need to call the value? Or can't I get the value by the session?
/nuxt.config.js
export default{
components: true,
buildModules: [
'#nuxtjs/dotenv'
],
modules: [
'#nuxtjs/dotenv', 'cookie-universal-nuxt',
],
router: {
middleware: ['auth']
},
serverMiddleware: [
'~/server/app.js',
],
}
/server/app.js
const express = require('express')
const app = express()
const session = require('express-session')
const cors = require('cors')
app.use(cors())
//body-parser added
app.use(express.json())
//session added
app.use(session({
secret: 'secret key',
resave: false,
saveUninitialized: true
}))
...
app.use('/login_router', require('./routes/login_router'))
/server/routes/login_router.js
const express = require('express');
const router = express.Router();
const path = require('path');
router.get('/testGetUserid', function(req, res){
req.session.userid = '10101'
console.log('req.session.userid>>>>>>', req.session.userid)
res.redirect('/login')
});
/pages/login.vue
<template>
<button #click="submitTest">Get the userid</button>
</template>
<script>
export default {
methods:{
submitTest(){
console.log('this.$session.userid>>>', this.$session.userid) // I want to see this value as 10101
}
}
}
</script>
I assume that you are using SPA mode.
So you can use API to get that userId.
router.get('/testGetUserid', function(req, res){
req.session.userid = '10101'
res.json({ userId: req.session.userid })
});
If you want to get userId in another endpoint, I think you can do like this. I haven't tried it but I believe the session is accessbile anywhere in your backend code once you have set it in /testGetUserid.
Example you have /user route
router.get('/user', function(req, res){
const userId = req.session.userid
// do something
res.json(someJSON)
});
in Nuxt
<script>
export default {
methods:{
submitTest(){
axios.get('/testGetUserid', { withCredentials: true }).then(res => {
// here you can get the userId, you can store it in variable or vuex
conosle.log(res.data.userId)
})
}
}
}
</script>
Related
I'm developing a register/login website which includes all features to make it work in an efficient and secure way using reactJS, NodeJS and Mysql.
Everything was working fine until I used express-session. In fact, when a user logs in, he will be redirected to a home page (obviously a session will be created) but when the user refreshes the page, It is expected to stay on the home page but the behavior I got is losing the session, thus being redirected to login page.
I looked for a fix and I already tried enabling credentials with Axios in the frontEnd and Cors in the backEnd but the problem is persisting.
This is my code:
server.js
const express = require('express');
const app = express();
const mysql = require('mysql2');
const cors = require('cors');
const validator = require('validator');
const {body, validationResult} = require('express-validator');
const session = require('express-session');
const cookieParser = require('cookie-parser');
app.use(express.json());
app.use(cors({
origin: ['http://localhost:3000'],
methods: ['GET', 'POST'],
credentials: true,
}
));
app.use(express.urlencoded({extended: true}));
app.use(cookieParser());
app.use(session({
name: 'session',
secret: 'crud',
resave: false,
saveUninitialized: false,
cookie: {
expires: 60 * 30,
sameSite: 'strict',
}
}
app.post('/login', (req, res) => {
const mail = validator.escape(req.body.mail);
const pass = validator.escape(req.body.pass);
const sqlSelect = 'SELECT * FROM login WHERE mail = ? AND pass = ?';
db.query(sqlSelect, [mail, pass], (err, result) => {
if (err) {
console.log(err);
}
if (result.length > 0) {
req.session.user = result;
req.session.loggedIn = true;
console.log(req.session.user);
res.send({message: 'success', session: req.session});
}
else {
res.send({message: 'Wrong combination Email/Password !'});
}
})
});
app.get('/login', (req, res) => {
console.log(req.session.user);
if (req.session.user){
res.send({
session: req.session,
message: 'logged'
});
}
else {
res.send({
message: 'Not logged'
});
}
});
app.js (login page)
Axios.defaults.withCredentials = true;
const onSubmit = () => {
Axios.post('http://localhost:9001/login', {
mail,
pass,
}).then((response) => {
console.log(response.data.message);
if (response.data.message === 'success') {
history.push('/home');
}
else {
setMessage(response.data.message);
}
});
};
home.js
export default function Home() {
const [user, setUser] = useState('');
const history = useHistory();
useEffect(() => {
Axios.get('http://localhost:9001/login', {withCredentials: true}).then((response) => {
console.log(response.data.message);
if (response.data.message === 'logged'){
setUser(response.data.session.user[0].mail);
}
else {
history.push('/');
}
})
//eslint-disable-next-line
}, []);
return (
<div>
<p>{user}</p>
</div>
)
}
I hope someone is able to suggest some fix to this. I know I can use localStorage but I want to use the session instead.
I am trying to access the req.user that passport creates when doing a google o auth strategy. I can access the req.user in the routes file below, but when I try to access it in my userController file it is showing up as undefined.
Why is user accessible in routes file but not userController?
googleAuthRoutes.js:
const passport = require('passport');
const requireLogin = require('../middlewares/requireLogin')
const cors = require('cors');
const axios = require('axios');
const Template = require('../models/Template');
const corsOptions ={
origin: true,
credentials:true, //access-control-allow-credentials:true
optionSuccessStatus:200
}
module.exports = app => {
app.get('/auth/google',
passport.authenticate('google', {
scope: ['profile', 'email']
}));
app.get(
'/auth/google/callback',
passport.authenticate('google'),
(req, res) => {
res.redirect('/dashboard');
}
);
app.post('/templates/create', async (req, res) => {
const { template, body } = req.body
console.log(req.user)
const newTemplate = new Template({
template: template,
body: body,
_user: req.user.id
})
try {
await newTemplate.save()
return res.status(200).json({
message: "Successfully saved template"
})
} catch (err) {
return console.log(err)
}
});
app.get('/api/logout', cors(), (req, res) => {
req.logout();
res.redirect('http://localhost:3000');
});
app.get('/api/current_user', (req, res) => {
res.send(req.user);
})
}
when I call the res.send(req.user) here above it sends the user no problem
But it is undefined with the /templates/create route middleware.
the console.log(req.user) is coming back as undefined??
index.js:
const express = require('express');
const cors = require('cors')
const mongoose = require('mongoose');
const cookieSession = require('cookie-session');
const passport = require('passport');
const keys = require('./config/keys');
const bodyParser = require('body-parser')
require("dotenv").config();
require('./models/GoogleUserModel'); // the user model must be placed before this services passport// this must be ran after requiring model bcuz this needs the model. ORDER
require('./models/UserModel');
require('./services/passport');
const corsOptions ={
origin:'http://localhost:3000',
credentials: true, //access-control-allow-credentials:true
optionSuccessStatus:200
}
const app = express();
app.use(cors(corsOptions))
mongoose.connect(keys.mongoURI, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
})
mongoose.connection.on('error', () => {
throw new Error (`unable to connect to database: ${keys.mongoURI}`)
});
app.use(bodyParser.json())
app.use(express.urlencoded( { extended: true }))
app.use(
cookieSession({
maxAge: 30 * 24 * 60 * 60 * 1000,
keys: [keys.cookieKey]
})
)
app.use(passport.initialize());
app.use(passport.session());
require('./routes/userRoutes')(app);
require('./routes/googleAuthRoutes')(app);
require('./routes/messageRoutes')(app);
app.use((err, req, res, next) => {
if (err.name === 'UnauthorizedError') {
res.status(401).json({"error" : err.name + ": " + err.message})
} else if (err) {
res.status(400).json({"error" : err.name + ": " + err.message})
console.log(err)
}
})
const PORT = process.env.PORT || 5000;
app.listen(PORT);
Again, Why is the req.user available in the app.get to /api/current_user but available in a post request to /templates/create?
Im trying to add the user.id to the schema when it saves so i can retrieve each template by the user.id and not show everyone everybody elses templates lol
I am using node and express with vue. I try to implement a middleware for my node routes, to check the login token and if it is wrong, redirect to the login page.
This is my code so far.
Main app.js file
const express = require('express');
const path = require('path');
const cors = require('cors');
const http = require('http');
const bodyParser = require('body-parser');
const app = express();
app.use(cors());
app.use(express.static(path.join(__dirname,'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}));
app.use(express.json());
app.use(express.urlencoded({extended:false}));
app.use('/login', require('./routes/login'));
app.use('/performance', require('./routes/performance'));
const port = 4000;
http.createServer(app).listen(port, ()=>{
console.log('server runs on port ', port);
});
Then in my routes I have
const express = require('express');
const token = require('../../lib/token');
router.get('/:product/dataquality/', token.validate(), (req, res)=>{
const product = req.params.product;
db.dataquality(product)
.then((resolved)=>{
console.log('route dataquality result', resolved);
res.json({success:true, data:resolved});
})
.catch((error)=>{
console.log('route dataquality error', error);
res.json({success:false, data:false});
});
});
And this token.validate middleware is
const jwt = require('jsonwebtoken');
const config = require('../db/config');
const validate = ()=>{
return (req, res, next)=>{
const token = req.get('Authorization');
const key = config.key;
jwt.verify(token, key,function(err, decoded) {
if (err){
console.log('token error');
res.redirect('/login');
}
if (decoded){
console.log('token ok');
next();
}
});
}
}
exports.validate = validate;
This works fine and I see the token console logs when I login in my app. If I go to the browser and edit the token (delete a couple of characters, but not completely remove it) so the token is there but is the wrong token, it has the wrong value :
I see in my console token error and I get no data, but the redirect to login page never happens.
If I do res.redirect('http://localhost:8080/login'); I still get no redirect.
What am I missing? How can I fix this?
If you think this is a Vue issue, let me know, so I can provide Vue routing code.
Thanks
EDIT
This the file that handles routes in Vue - router.js
import Vue from 'vue'
import Router from 'vue-router'
import store from '#/components/store';
import Login from './components/Login.vue'
import Performance from './views/Performance.vue'
Vue.use(Router)
const router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: '/login',
name: 'login',
component: Login,
},
{
path: '/performance',
name: 'performance',
component: Performance,
beforeEnter: (to, from, next) => {
if (store.state.login.token == null || !store.state.login.token) {
next('/login');
}
else{next();}
}
},
{
path: '*',
redirect: '/login'
}
]
})
router.beforeEach((to, from, next) => {
store.dispatch('resetAccessToken');
if (to.fullPath === '/performance') {
if (!store.state.login.token) {
console.log('VUE route go to login');
next('/login');
}
}
if (to.fullPath === '/login') {
if (store.state.login.token) {
console.log('VUE route browse normally');
next('/performance');
}
}
next();
});
If I search for "route" in my browser console to find console.log('VUE route go to login'); or console.log('VUE route browse normally'); it says it found 160 but I cannot see none.
I still get no data, but I can browse normally to empty Vue pages. Node or Vue redirect should work and send me to login , but none works, so I still can browse around.
Thanks
I am using exrepss framework in nodejs.
Server side code:
This is my server side code :
router.post('/signup', function (req, res, next){
console.log("here i am " + request.body)
User.findOne({ $or: [{ 'local.email': req.body.email }] }, function(err, user) {
if (err) {
res.json(err);
}
if (user) {
if (user.local.email == req.body.email) {
res.json({msg:"This email is already taken."})
}
} else {
var userData = new User();
userData.local.email = req.body.email;
userData.local.password = req.body.password;
userData.save()
.then (res.json)
.catch(err => {
console.log(err);
res.status(400).json({msg:"unable to save to database"});
})
}
})
});
While triggering this api from Postman , i am passing this as the body in the json format.
{
"email": "qweeeee",
"password": "1233"
}
Missed information:
I am also using session in my app.js to
..
app.use(session({
resave : true ,
saveUninitialized : true,
secret : 'keyboard cat',
store : new MongoStore({ mongooseConnection: mongoose.connection}), //starting a new session
cookie : {maxAge : 180 * 60 * 1000}
}
));
..
I believe this has something to do with the post api not getting called. If i remove this code , my GET APIs also dose not work.
my app.js file looks like this.
...
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var bodyParser = require('body-parser');
var expressHbs = require('express-handlebars');
var csurf = require ('csurf');
var cors = require('cors');
var indexRouter = require('./routes/index');
var mongoose = require ('mongoose');
var session = require('express-session')
var passport = require('passport');
var flash = require('connect-flash');
var MongoStore= require('connect-mongo')(session);
const https = require('https');
require('./config/passport');
var app = express();
app.use(cors());
app.use(express.json());
app.use(bodyParser.json());
app.use('/css', express.static(__dirname + '/node_modules/bootstrap/dist/css'));
mongoose.connect("mongodb://localhost:27017/shopping-cart", {
useNewUrlParser: true
});
app.use(logger('dev'));
app.use(session({
resave : true ,
saveUninitialized : true,
secret : 'keyboard cat',
store : new MongoStore({ mongooseConnection: mongoose.connection}), //starting a new session
cookie : {maxAge : 180 * 60 * 1000}
}
));
app.use('/', indexRouter);
...
Make sure you are parsing the request body. Something like this
const bodyParser = require("body-parser");
app.use(bodyParser.json());
router.post('/signup', function (req, res, next){
// access req.body here
});
👨🏫 You can use this code below: 👇
router.post('/signup', function (req, res, next){
// make sure this is not undefined
console.log(req.body);
User.findOne({ $or: [{ 'local.email': req.body.email }] }).then(user => {
if(user) {
return res.json({msg:"This email is already taken."});
}
var userData = new User(req.body);
userData.save().then(result => {
// make sure the
console.log(result);
res.send(200).json(result);
}).catch(err => {
console.log(err);
res.status(400).json({msg:"unable to save to database"});
})
}).catch(ex => {
console.log(ex.message);
res.status(500).send(ex);
})
});
💡 Make sure your req.body is not undefined
👨🏫 If your req.body is undefined, then you can use this code below in your app.js or server.js.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
I hope it can help you 🙏.
I'm trying to have a session containing user data in the node.js/express FW.
I'm using express-session. I'm not using session store yet.
I have 2 pages in the client (angular) where I iterate between - Login and Dashboard. The idea is to create the session after successful login, then routing to the dashboard page. In the dashboard page I have an anchor with routinlink to the login:
<a [routerLink]="['/login']" >BackToLogin</a>
When navigating back to the loginPage (when activating a route), I execute a service with an end-point to the express server which check if the request has a session with a request in it (I expect it to be). The problem is that I see that the session is not the same session (the id changes)
See my code:
Node.js side - server.js file:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const session = require ('express-session');
var cookieParser = require('cookie-parser');
const SESS_NAME = 'sid';
app.use(session({
name:SESS_NAME,
key: 'user_sid',
resave:false,
saveUninitialized:false,
secure: process.env.NODE_ENV ==="production",
secret:'<some random text>',
cookie:{
httpOnly: true,
secure: process.env.NODE_ENV ==="production",
expires: 60000
}
}));
app.use(bodyParser.text());
app.use(bodyParser);
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cors()); //No limitation for test reasons
app.use(cookieParser());
//disabled on purpose
//var sessionManagement = require('./middleware/sessionManagement');
// API
app.use("/", require("./api/v1/routes.js"))//This file includes:
/*
const express = require('express');
const router = express.Router();
router.use("/login", require('./login'));
router.use("/session", require('./session'));
module.exports = router;
*/
...etc
app.listen(config.port, () => console.log(`Process ${process.pid}: Listening on port ${config.port}`));
login.js on the server: responsible for validating user and store user data in session:
const express = require('express');
const router = express.Router();
const schema = require('./objectSchemaJson.schema.json');
const scehmaCheck = require('../../middleware/checkForSchema')(schema);//this is
a schema check (middleware) - if suceeded continue (next)
const storeSession = (req, dataResult) =>
{
if (<dataResult return with valid use data>) //This is "where the magic happanes"
{
req.session.user = {
username: <get userName from dataResult>,
ID: <Get ID from dataResult>,
Role: <Get Role from dataResult>
}
}
}
router.use("/", scehmaCheck, (req, res, next) => {
return GetUserDataFROmDB(req.body).then((dataResult) => { //reaching the DB - not mentioned here on purpose
storeSession(req, dataResult); // This is where the session set with user data
res.status(200).json(dataResult);
}).catch((err) => {
next({
details: err
})
});
});
module.exports = router;
This is the end point on the server that responsible for getting the session - session.js - This is where the problem appears - the res.session has a session ID which is different that the one I created after the login
const express = require('express');
const router = express.Router();
hasSession : function(req, res) //This is where the problem appears - the res.session has a session ID which is different that the one I created after the login
{
if (req.session.user)
{
res.status(200).json(
{
recordsets: [{Roles: req.session.Roles, UserName: req.session.user.username}]
});
}
else{
res.status(200).json({});
}
}
router.use("/", (req, res, next) => { return sessionManagement.hasSession(req, res, next)});
module.exports = router;
Client side:
//HTML:
<div>
<label>Username:</label>
<input type="text" name="username" [(ngModel)]="userName" />
</div>
<div>
<label>Password:</label>
<input type="password" name="password" [(ngModel)]="password"/>
</div>
<div>
<button (click)="login()">Login</button>
</div>
//COMPONENT:
login()
{
this.srv.login(this.userName, this.password).subscribe(result =>
{
if (<result is valid>)
{
this.router.navigate(['/dashboard']);
}
}
);
}
//This reach the node.js endpoint and routing to the session.js end point - it is executes when the router-outlet activated in the app.component:
/*
onActivate(componentRef : any)
{
if (componentRef instanceof LoginComponent)
{
componentRef.getSession();
}
}
*/
getSession() : void
{
this.sessionService.getSession().subscribe( result =>
{
if (<result is valid>)
{
this.router.navigate(['/dashboard']);
}
});
}
I found a similar question on github - no solution yet:
https://github.com/expressjs/session/issues/515
but it might be a cookie <-> server configuration issue.
Found the problem - the root cause was that the client didn't send a cookie when making an httprequest.
2 things needed to be done in order to solve the problem:
1. CORS Definition
Set the CORS definition to creadentials: true along with the origin (the host name of the client, which is probably with a different port\hostname):
app.use(cors({
origin: config.origin,
credentials: true
}));
2. Set crendentials
For every http rest method (get and post, in my case) add withCredentials property with a value of true:
return this.http.get<any>(<path>, { withCredentials: true })
or
return this.http.post<any>(<path>, <body>, { withCredentials:true })