Julio
Julio

Reputation: 407

req.session is not storing data

I'm trying to implement a login system where an user can register to a website, and then sign in with his account. Once the user is logged in, he can edit his personal information.

To check if the user is logged in, I'm trying to set req.session.isLoggedIn to true and then check if that value is true to access some areas of the website. The thing is that just after I signed in, I print the value of req.session and I see my just setted valued, but after that, when I try to check the value of req.session.isLoggedIn in another route, I get no value.

Here's my code:

const express = require('express');
const app = express();
var { Client } = require('pg');
var bcrypt = require('bcrypt');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var cors = require('cors');
var path = require('path');
var session = require('express-session');
var url = require("url");


app.use(cors());
app.use(express.static(path.join(__dirname, 'client/build')));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 600000000 }}))

const client = new Client({
  user: 'xxxxxxxxxxxxx',
  host: 'xxxxxxxxxxxxx',
  password: 'xxxxxxxxxxxxxxx',
  database: 'xxxxxxxxxxxxxx',
  port: 5432,
  ssl: true
})
client.connect();

/*Rutas*/

/*Seleccionar huellas pertenecientas a una cierta categoria*/
app.get('/api/huellas/:categoria', (req, res) => {
  client.query('SELECT * FROM huellas WHERE categoria = $1 AND activo = TRUE', [req.params.categoria], (err, query) => {
    if (err) {
      console.log(err.stack);
    } else {
      res.json(query.rows);
    }
  });
});

/*Listar todas las huellas*/
app.get('/api/mostrarHuellas', function(req, res, next) {
  client.query('SELECT * FROM huellas', (err, query) => {
    if (err) {
      console.log(err.stack);
    } else {
      res.json(query.rows);
    }
  });
});

app.get('/api/buscarHuellas/', function(req, res) {
  console.log(req);
  console.log("nombre: " + req.query.nombre + " categoria: " + req.query.categoria + " estado: " + req.query.estado);
  client.query('SELECT * FROM huellas WHERE (nombre = $1 AND categoria = $2 AND estado =  $3) AND activo = TRUE', [req.query.nombre, req.query.categoria, req.query.estado], (err, query) => {
    if (err) {
      console.log(err.stack);
    } else {
      res.json(query.rows);
    }
  });
});

app.post("/api/registro", function(req, res) {
  var email = req.body.email;
  var password = bcrypt.hashSync(req.body.password, 10);
  client.query('INSERT INTO usuarios(email, password, huella) VALUES ($1, $2, $3)', [email, password, req.body.huella], function(err, result) {
    if(err) {
      //console.log(err.stack);
      res.json(err);
    }
    else {
      console.log('row inserted');
      res.json("ok");
    }
  });
});

app.post("/api/login", function(req, res) {
  client.query('SELECT * FROM usuarios WHERE email = $1', [req.body.email], (err, query) => {
    if (err) {
      console.log(err.stack);
    } else {
      if(bcrypt.compareSync(req.body.password, query.rows[0].password)){
        req.session.isLoggedIn = true;

        console.log(req.session);
        res.json("ok");
      }
      else{
        res.json("clave invalida");
      }
      res.end();
    }
  });
});

app.get("/api/logout", function(req, res) {
  req.session.destroy();
});

app.get("/api/sessions", function(req, res){
  console.log(req.session);
  if(req.session.isLoggedIn) {
    console.log("logged in!");
  }
});


const port = process.env.PORT || 5000;
app.listen(port);

When I access /api/login/ I receive this output in the terminal, I can see isLoggedIn:

    Session {
  cookie: 
   { path: '/',
     _expires: 2017-09-05T00:29:19.786Z,
     originalMaxAge: 600000000,
     httpOnly: true },
  isLoggedIn: true }

But after that, when I access /api/sessions/ I receive this output:

Session {
  cookie: 
   { path: '/',
     _expires: 2017-09-05T00:29:21.451Z,
     originalMaxAge: 599999999,
     httpOnly: true } }

I'm using Nodejs and Expressjs. Also, I'm serving some static file stored in /client/build, and they are working fine.

Thanks in advance!

EDIT:

Here's what my handle login method looks like, I'm using react and react-router 4:

handleSubmit(event){
   event.preventDefault();
   fetch('/api/login', {
   method: 'post',
   headers: {'Content-Type':'application/json'},
   body: JSON.stringify({
     "email": document.getElementById("email").value,
     "password": document.getElementById("pwd").value
   })
   })
     .then(response => response.json())
     .then(res => {
        switch (res) {
          case "clave invalida":
            alert("clave invalida");
            break;
          case "ok":
            alert("sesion iniciada");
            this.props.history.push("/");
            break;
         default:
           alert("Error. Contacte a un administrador");
           break;
       }
     })
     .catch(err => console.log(err));
  };

Upvotes: 3

Views: 4348

Answers (2)

Julio
Julio

Reputation: 407

Well, I just found a solution for my problem. I used the solution posted by @ytibrewala here and the comment made by @nlawson here. This is what I did:

Apparently, by default, fetch method doesn't send cookies, so you need to set the credentials parameter inside the AJAX call, I did it this way:

AJAX call

  handleSubmit(event){
   event.preventDefault();
   fetch('http://localhost:5000/api/login', {
   method: 'post',
   credentials: 'include',
   headers: {'Content-Type':'application/json'},
   body: JSON.stringify({
     "email": document.getElementById("email").value,
     "password": document.getElementById("pwd").value
   })
   })
     .then(response => response.json())
     .then(res => {
       console.log(res);
       if(res.isLoggedIn){
         alert("Signed in");
         this.props.history.push("/hueprint");
       }
       else{
         alert("Invalid user or password");
       }
     })
     .catch(err => console.log(err));
  };

I used include because I'm not working with the same origin. More information about the values that the credentials parameter accepts can be found here

Then, I was facing a CORS issue in my browser, so I changed this on my index.js file on my back end:

index.js

app.use(cors({credentials: true, origin: true}));

Now, everytime I use my handleSubmit method in my website, and I checked the test route that prints req.session I see my isLoggedIn parameter properly setted.

I leave my route, for those who want to see it:

app.post("/api/login", function(req, res) {
  client.query('SELECT * FROM usuarios WHERE email = $1', [req.body.email], (err, query) => {
    if (err) {
      console.log(err.stack);
    }
    else {
      if(bcrypt.compareSync(req.body.password, query.rows[0].password)){
        console.log("password matches");
        req.session.isLoggedIn = true;
        req.session.save();
        res.send(req.session);
      }
      else{
        console.log("password doesn't match");
        req.session.isLoggedIn = false;
        req.session.save();
        res.send(req.session);
      }
    }
  });
});

Upvotes: 5

C.Unbay
C.Unbay

Reputation: 2826

You need to send the cookies with the res object whenever you want to save them. Here is my code and it works. Check it out.

app.use(session({
  secret: 'keyboard cat',
  resave: true,
  saveUninitialized: true,
}))    


app.get("/", function(req, res){
  if(req.session.views){
    req.session.views++;
  }else{
    req.session.views = 1;
  }
  res.status(200).send(req.session);
})


app.get("/checkerPage", function(req, res){
  console.log(req.session); //it logs the correct data.
  res.send("whatever");
})

//post req

app.post("/post", function(req, res){
  req.session.user = "myname";
  res.send(req.session);
  console.log(req.session);
});

my index html

<form action="/post" method="post">
  <input type="text" name="myName" value="">
  <input type="submit" name="" value="submit">
</form>

Upvotes: 1

Related Questions