Conditional cookies expiration depends on "Remember me" box, (using passport.js) - authentication

I'm a new programmer :)
I'm trying to build an authentication system using passport.js.
Now, I want to determine the expiration of the cookies, depend on "Remember me" checkbox - For the example I chose: if “remember me” cookie expires after 2 minutes, otherwise cookie expires after 1 minute.
The problem is that it doesn't change the cookie's maxAge (it still 1 minute)
my code:
login.hbs
<body class="border border-2 border" style="margin-top: 15%; margin-right: 30%; margin-left: 30%">
<form action="/login" method="POST" class="form-signing container" style="max-width: 30rem">
<div class="text-center">
<!-- <img class="mb-4" src="public/images/wine4u_logo.jpeg" alt="" width="72" height="72"> -->
<h1 class="h3 mb-3 font-weight-normal">Login</h1>
<p>Please Enter your credentials in order to enter our store.</p>
</div>
<hr>
{{#if error}}
<div class="alert alert-danger">{{error}}</div>
{{/if}}
<div class="mb-3 text-left">
<label for="email" class="form-label"><b>Email</b></label>
<input type="email" placeholder="Enter Email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label"><b>Password</b></label>
<input type="password" placeholder="Enter Password" class="form-control" id="password" name="password" required>
</div>
<div class="checkbox mb-3 text-center">
<label>
<input type="checkbox" class="form-label" name="rememberMe" value="remember-me"> Remember me
</label>
<!-- <label for="checkbox"><b>Remember Me?</b></label> -->
<!-- <input type="checkbox" name="rememberMe"> -->
</div>
<div class="text-center">
<button type="submit" class="btn btn-lg btn-primary btn-block">Login</button>
</div>
</form>
<hr>
<form action="/register" class="text-center">
<button type="" class="btn btn-lg btn-secondary btn-block">Sign up page</button>
</form>
<!-- Register -->
</body>
app.js:
if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}
const express = require("express");
const path = require("path");
const bodyParser = require("body-parser");
const exphbs = require("express-handlebars");
const bcrypt = require("bcrypt");
const passport = require("passport");
const flash = require("express-flash");
const session = require("express-session");
const initializePassport = require("./public/javascript/passport-config");
const methodOverride = require("method-override");
initializePassport(
passport,
(email) => users.find((user) => user.email === email),
(id) => users.find((user) => user.id === id)
);
const app = express();
let users = [];
let cookieLength = 60 * 1000;
// handleBars middleware
app.engine(".hbs", exphbs.engine({ defaultLayout: "main", extname: ".hbs" }));
app.set("view engine", ".hbs");
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: false }));
app.use(flash());
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
rolling: true,
cookie: { maxAge: cookieLength },
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use(methodOverride("_method"));
app.get("/", checkAuthenticated, async (req, res) => {
res.render("index", { title: "Welcome to my site" });
});
app.get("/login", checkLoggedIn, async (req, res) => {
res.render("pages/login", {
title: "login page",
noHeader: true,
error: req.flash("error"),
csrf: "CSRF token goes here",
});
});
app.post(
"/login",
checkLoggedIn,
defineCookieLength,
passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login",
failureFlash: true,
})
);
app.get("/register", checkLoggedIn, (req, res) => {
res.render("pages/register", { title: "register page", noHeader: true });
});
app.post("/register", async (req, res) => {
try {
const hashedPassword = await bcrypt.hash(req.body.password, 10);
users.push({
id: Date.now().toString(),
username: req.body.name,
email: req.body.email,
password: hashedPassword,
});
console.log("after:", users);
res.redirect("login");
} catch {
res.redirect("/register");
}
});
app.delete("/logout", function (req, res, next) {
req.logout(function (err) {
if (err) {
return next(err);
}
res.redirect("/login");
});
});
app.get("/about", checkAuthenticated, async (req, res) => {
// console.log("users in /login:", users)
res.render("pages/about", { title: "About us" });
});
function defineCookieLength(req, res, next) {
if (req.body.rememberMe === "on") {
req.session.cookie.maxAge = 120 * 1000;
next();
return;
}
next();
}
// validate that the user is already logged in before let him see other pages
function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect("/login");
}
// validate that user can't use login/register pages if he is already logged in
function checkLoggedIn(req, res, next) {
if (req.isAuthenticated()) {
return res.redirect("/");
}
next();
}
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => {
console.log(`Server Running on port: http://localhost:${PORT}`);
});
passport-config.js
const LocalStrategy = require("passport-local").Strategy;
const bcrypt = require("bcrypt");
function initialize(passport, getUserByEmail, getUserById) {
const authenticateUser = async (email, password, done) => {
const user = getUserByEmail(email);
if (user == null) {
return done(null, false, { message: "No user with that email" });
}
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user);
} else {
return done(null, false, { message: "Password incorrect" });
}
} catch (err) {
return done(err);
}
};
passport.use(new LocalStrategy({ usernameField: "email" }, authenticateUser));
passport.serializeUser((user, done) => done(null, user.id));
passport.deserializeUser((id, done) => {
return done(null, getUserById(id));
});
}
module.exports = initialize;

Related

Need help Posting external API call to a local postgres database

I'm working on a project that successfully displays the requested API call on a card in my HTML. I want to use a button click on that card to POST the same information to my local database of Favorites, then Get that Database to display on screen when called.
I've created the routes already that work in postman, just can link the external database to my local server.
//GameZ Backend Project
// document.getElementById('search').addEventListener('click', singleGame)
const express = require('express');
const app = express();
const { sequelize, Game, Favorites, Wishlist, User } = require('./models')
const bodyParser = require('body-parser');
const es6Renderer = require('express-es6-template-engine');
const fetch = require("node-fetch");
// const prohairesis =reqiure("prohairesis");
// const dotenv = require("dotenv");
//app.use('/', require('./routes/endpoints'));
const winston = require('winston');
const moment = require('moment');
const pg = require('pg-promise')();
const bcrypt = require('bcrypt');
const { response } = require('express');
//To convert the request to readable json format, we use bodyparser package
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false}))
app.engine('html', es6Renderer);
app.set('views', 'templates');
app.set('view engine', 'html');
app.use(express())
const logger = winston.createLogger({
level: 'info',
defaultMeta: { service: 'Game' },
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
]
})
// Middleware is the mediary that modifies information sent between the client and server
app.all('*', (req, res, next) => {
logger.info({
"Action": req.method,
"Path": req.path,
"Content_Type": req.header('Content-Type'),
"Body": req.body,
"Time": moment().format('MM/DD/YYYY, h:mm:ss a')
})
next()
})
app.get('/home', (req, res) => {
res.render('index2', {
locals: {
// name: '',
// games: []
}
});
})
//Get all games from gameInfo (app.get)
app.get('/gameInfo', async (req, res) => {
let gaming = await Game.findAll();
res.send(gaming)
console.log(gaming)
})
// Get a single game from the gameList (app.get)
// function singleGame(){
// let SGame = document.getElementById("singleGame").value
// let idArray = []
app.post('/home', async (req,res)=> {
const userInput = req.body.search;
const urlEncodedSearchString = encodeURIComponent(userInput);
let games = await fetch(`https://rawg.io/api/games?key=c1be38abe1e74ea3a7b554f19b8a9df6&search=${urlEncodedSearchString}`)
let gamesJson = await games.json()
let allGames = gamesJson.results.slice(0,8)
res.render('index3', {
locals: {
games: allGames,
name: ''
}
});
})
app.get('/home/2', async (req,res) => {
let gameCard = {}
//fetch using search by name
fetch(`https://rawg.io/api/games?key=c1be38abe1e74ea3a7b554f19b8a9df6&search=batman`)
.then((response) =>{
return response.json()
})
.then(data => {
console.log(data)
for (let index = 0; index < data.results.length; index++) {
gameCard = {
name: data.results[index].name,
id: data.results[index].id,
rating:data.results[index].rating,
released: data.results[index].released,
img: data.results[index].background_image
}
console.log(gameCard)
}
res.send(gameCard)
})
})
app.get('/oneresult/:gameslug' , async (req, res) => {
let faveCard = {}
console.log(req.params.gameslug, "IM HERE")
let games = await fetch(`https://rawg.io/api/games/${req.params.gameslug}?key=c1be38abe1e74ea3a7b554f19b8a9df6`)
console.log(games)
let gamesJson = await games.json()
console.log(gamesJson)
let allGames = gamesJson
console.log(allGames)
res.render('FavoritesWish', {
locals: {
game: allGames,
name: ''
}
});
} )
app.get('/gameList', async (req, res) => {
let gaming = await Game.findOne ({
where: {
}
})
if (gaming == null) {
res.statusCode = 400;
res.render('Not found');
} else {
res.statusCode = 200;
// res.send(gaming);
res.send('gaming', {
locals: {
gaming,
}
});
}
})
// }
// Add a game to the gameList
app.post('/gameInfo', async (req, res) => {
let createdUser = await Game.create(
{
gamename: req.body.gamename,
gameid: req.body.gameid,
star: req.body.star,
review: req.body.review,
username: req.body.username
}
)
res.statusCode = 200;
res.send(createdUser);
});
//Get all Favorites from Info (app.get)
// app.get('/favInfo', async (req, res) => {
// let favoritesgame = await Favorites.findAll();
// res.send(favoritesgame)
// })
// Get a single game from the favList (app.get)
app.get('/favList/:id', async (req, res) => {
let favoritesgame = await Favorites.findOne ({
where: {
id: req.params.id
}
})
if (favoritesgame == null) {
res.statusCode = 400;
res.render('Not found');
} else {
res.statusCode = 200;
// res.send(favoritesgame);
res.render('gaming', {
locals: {
favoritesgame,
}
});
}
})
// Add a game to the FavoritesList
app.post('/favInfo', async (req, res) => {
let createdFavorites = await Favorites.create(
{
gamename: req.body.gamename,
platform:req.body.platform,
gameid: req.body.gameid,
star: req.body.star,
releasedate: req.body.releasedate,
username: req.body.username
}
)
res.statusCode = 200;
res.send(createdFavorites);
});
//Get all Wishlist from Info (app.get)
app.get('/wishInfo', async (req, res) => {
let wishlistgame = await Wishlist.findAll();
res.send(wishlistgame)
})
// Get a single game from the WishList (app.get)
app.get('/wishList/:id', async (req, res) => {
let wishgame = await Wishlist.findOne ({
where: {
id: req.params.id
}
})
if (wishgame == null) {
res.statusCode = 400;
res.send('Not found');
} else {
res.statusCode = 200;
// res.send(wishlistgame);
res.render('wishlistgame', {
locals: {
wishgame,
}
});
}
})
// Add a game to the WishList
app.post('/wishInfo', async (req, res) => {
let createdwishList = await Wishlist.create(
{
gamename: req.body.gamename,
gameid: req.body.gameid,
rating: req.body.rating,
username: req.body.username
}
)
res.statusCode = 200;
res.send(createdwishList);
});
// Delete a game from the gameList
app.delete('/gameInfo/:gamename', async (req, res) => {
let deletedGames = await Game.destroy({
where: {
gamename: req.params.gamename
}
})
res.sendStatus(200).send(deletedGames);
})
// Delete a game from the Favorites
app.delete('/favInfo/:gamename', async (req, res) => {
let deletedGames = await Favorites.destroy({
where: {
gamename: req.params.gamename
}
})
res.sendStatus(200).send(deletedGames);
})
// Delete a game from the gameList
app.delete('/wishInfo/:gamename', async (req, res) => {
let deletedGames = await Wishlist.destroy({
where: {
gamename: req.params.gamename
}
})
res.sendStatus(200).send(deletedGames);
})
// Add a game to the gameList
app.post('/favInfo', async (req, res) => {
let createdUser = await Favorites.create(
{
gamename: req.body.gamename,
gameid: req.body.gameid,
star: req.body.star,
review: req.body.review,
username: req.body.username
}
)
res.statusCode = 200;
res.send(createdUser);
});
// app.post('/pushFav', async (req,res)=>{
// gameCard = {
// name: data.results[index].name,
// id: data.results[index].id,
// rating:data.results[index].rating,
// released: data.results[index].released,
// img: data.results[index].background_image
// }
// console.log(gameCard)
// }
// res.send(gameCard)
// });
//Update the meta for a game
app.patch('/gameInfo/:gamename', async (req, res) =>{
let gPatch = await Game.update(
{
gamename: req.body.gamename,
gameid: req.body.gameid,
star: req.body.star,
review: req.body.review,
username: req.body.username,
}, {
where:{
gamename: req.params.gamename
}
}
)
res.sendStatus(200).send(gPatch);
})
//Update the meta for a Favorites
app.patch('/favInfo/:gamename', async (req, res) =>{
let gPatch = await Favorites.update(
{
gamename: req.body.gamename,
gameid: req.body.gameid,
star: req.body.star,
review: req.body.review,
username: req.body.username,
}, {
where:{
gamename: req.params.gamename
}
}
)
res.sendStatus(200).send(gPatch);
})
//Update the meta for a Wishlist
app.patch('/wishInfo/:gamename', async (req, res) =>{
let gPatch = await Wishlist.update(
{
gamename: req.body.gamename,
gameid: req.body.gameid,
star: req.body.star,
review: req.body.review,
username: req.body.username,
}, {
where:{
gamename: req.params.gamename
}
}
)
res.sendStatus(200).send(gPatch);
})
// User login
app.post('/login', (req, res) => {
const { email, password } = req.body;
models.User.findOne({
where: { email: email }
}).then((user) => {
if (!user) {
res.json({ error: 'no user with that username' })
return;
}
bcrypt.compare(password, user.password, (err, match) => {
if (match) {
req.session.user = user;
res.json({ user_id: user.id, success: true })
} else {
res.json({ error: 'incorrect password' })
}
})
})
})
app.listen(8500, async ()=> {
console.log('Server is running on port 7500')
await sequelize.sync()
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Response Page</title>
</head>
<body>
<div class="flexbox">
<header class="header">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="./index2.html">Gamz+</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="./FavoritesWish.html">Favorites</a>
</li>
<li class="nav-item">
<a class="nav-link" href="">Page 2</a>
</li>
<li class="nav-item">
<a class="nav-link" href="">Page 3</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<!-- <li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Something else here</a></li> -->
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
</ul>
<form method="POST" action="/home" class="d-flex">
<input name="search" class="form-control me-2 search-button" type="text" placeholder="Search" aria-label="Search">
<button class="btn btn-sm btn-block btn-primary mt-auto" type="submit">Search</button>
</form>
</div>
</div>
</nav>
</header>
<div>
<div class="card" style="width: 18rem;">
<img src="${game.background_image}" class="card-img-top" alt="" width="100" height="120">
<div class="card-body">
<h5 id="title" class="card-title">${game.name} </h5>
<p class="card-text">Platform ${game.parent_platforms.map((platform)=>{
return platform.platform.name
})} </p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">Rating ${game.rating}</li>
<li class="list-group-item">Game ID ${game.id}</li>
<li class="list-group-item">Release Date ${game.released}</li>
</ul>
<div class="card-body">
<a id="fav" href="#" class="card-link">Add to Favorites</a>
<a id="wish" href="#" class="card-link">Add to Wishlist</a>
<div class="input-group mb-3">
<button class="btn btn-outline-secondary" type="button" id="button-addon2">Add to Favorite</button>
</div>
</div>
</div>
</div>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
<script src="serverBP.js"></script>
</body>
</html>

issues getting data to show on screen from SQL

This is a React Js project that is using Axios, Cors, Express, and Node JS connecting to an SQL database.
I am trying to get the data from an SQL table and have it show on the screen either in a div or p tag each row on its own line. At this time I am able to get it to console.log inside my VS Code terminal from my server.js side as well as console log the data inside my browser console from my frontend of ProductList.js. I do not get any errors in any of my consoles just the data that I would like displayed on the screen.
The below is my server.js
const bodyParser = require('body-parser');
const express = require('express');
cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }))
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/collectors', function (req, res) {
var sql = require("mssql");
const config = {
user: 'XXXXXXX',
password: 'XXXXXXX',
server: 'XXXXXXX',
database: 'XXXXXXX',
options: {
trustServerCertificate: true,
trustedConnection: false,
enableArithAbort: true
},
}
sql.connect(config).then(pool => {
return pool.request()
.query('select * from CollectorAssignment.tCollectors ').then(result => {
console.dir(result)
res.send(result)
})
}).catch(err => {
console.log("error at line24: ", err)
})
sql.on('error', err => {
console.log("error at line28: ", err)
})
});
app.listen(5000, () => {
console.log('listening on port 5000')
});
The below is my ProductList.js
import React from "react";
import axios from 'axios';
class ProductList extends React.Component {
state = {
loading: true,
error: "",
data: []
};
componentDidMount() {
this.getCollectorList();
}
getCollectorList = () => {
this.setState({ loading: true });
return axios
.get(
'http://localhost:5000/collectors'
)
.then(result => {
console.log(result);
this.setState({
CollectorList: result.data.items,
loading: false,
error: false
});
})
.catch(error => {
console.error("error: ", error);
this.setState({
error: `${error}`,
loading: false
});
});
};
render() {
const { loading, error, data } = this.state;
if (loading) {
return <p className="productList">Loading ...</p>;
}
if (error) {
return (
<p className="productList">
There was an error loading the collectors.{" "}
<button onClick={this.loadData}>Try again</button>
</p>
);
}
return (
<div className="productList">
<h1>Collector List</h1>
{data.map(result => <p className="productList">{result.CollectorList}</p>)}
</div>
);
}
}
export default ProductList;
Screenshot of my VS Code console data I get the same info in my browser console which is a total of 16 rows of data that I need displayed on the screen
I have gotten this to start working for me here are the changes I have made to the two files I provided. I was calling a few areas improperly and found that I was looking at some ways for SQL and I am using SQL so some connections to the DB were different which caused some issues small syntax things mainly.
Server.js
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const config = require('./src/dbfiles/dbConfig')
const app = express();
app.use(cors());
app.use(bodyParser.json({ extended: true }));
var sql = require("mssql");
app.get('/getCollectors', (req, res) => {
sql.connect(config).then(pool => {
return pool.request()
.query('SELECT * FROM CollectorAssignment.tCollectorsTest').then(result => {
res.send(result.recordset)
})
})
})
app.post('/addCollector', function (req, res) {
sql.connect(config).then(pool => {
return pool.request()
.query(`INSERT INTO CollectorAssignment.tCollectorsTest
(
Active,
FirstName,
MiddleInitial,
LastName,
CollectorCode,
CreationDate,
CollectionTeamID
) VALUES (
${req.body.Active},
'${req.body.FirstName}',
'${req.body.MiddleInitial}',
'${req.body.LastName}',
'${req.body.CollectorCode}',
'${req.body.CreationDate}',
1
)`)
.then(result => {
res.send(result)
})
})
});
app.post('/updateCollector', function (req, res) {
sql.connect(config).then(pool => {
return pool.request()
.query(`UPDATE CollectorAssignment.tCollectorsTest
SET ${req.body} = ${req.body}
WHERE ${req.body} = ${req.body}
`)
.then(result => {
res.send(result)
})
})
});
app.delete('/deleteCollector/:CollectorID', (req, res) => {
sql.connect(config).then(pool => {
return pool.request()
.query(`DELETE FROM CollectorAssignment.tCollectorsTest WHERE CollectorID = ${req.params.CollectorID}`).then(result => {
res.send(result.recordset)
})
})
})
app.listen(5000, () => {
console.log('running on port 5000');
})
ProductList.js
import "./userList.css";
import React from "react";
import axios from 'axios';
import { Link } from "react-router-dom";
import { DeleteOutline, Edit } from "#material-ui/icons";
class UserList extends React.Component {
state = {
Collectors: '',
collectorList: []
}
componentDidMount() {
this.getCollectors()
}
getCollectors = () => {
axios.get('http://localhost:5000/getCollectors')
.then((result) => result.data)
.then((result) => {
this.setState({collectorList: result});
});
};
render() {
return (
<div className="userList">
<h3>Collectors</h3>
<table className="blueTableHeaders">
<thead>
<tr>
<th>Active</th>
<td>Collectors</td>
<td>Aging Bucket</td>
<td>Program Code</td>
<td>Finance Company</td>
<td></td>
</tr>
</thead>
</table>
{this.state.collectorList.map((Collectors) => (
<div>
<table className="blueTableData">
<thead>
<tr>
<th><input type="checkbox" name="Active" defaultChecked={Collectors.Active === false ? false : true}/></th>
<td>{Collectors.FirstName} {Collectors.LastName} | {Collectors.CollectorCode}</td>
<td>
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
</td>
<td>
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
</td>
<td>
<input type="checkbox" />
<input type="checkbox" />
<input type="checkbox" />
</td>
<td>
<Link to="/updateUser:CollectorID">
<Edit className="editCollector" />
</Link>
<Link to="/deleteUser:CollectorID">
<DeleteOutline className="deleteCollector"/>
</Link>
</td>
</tr>
</thead>
</table>
</div>
))}
<Link to="/newUser">
<button className="userListAddButton">Add Collector</button>
</Link>
<Link to="/deleteUser">
<button className="userListDeleteButton">Delete Collector</button>
</Link>
</div>
);
}
}
export default UserList;

Cant´t get cookie - Express

I created a server with express and have some get/post routes.
In the login page, I have a page that shows the form to login:
app.get("/login", (req, res) => {
res.send(`<h1>Iniciar sesión</h1>
<form method='post' action='/login'>
<input type='email' name='email' placeholder='Email' required />
<input type='password' name='password' placeholder='Contraseña' required />
<input type='submit' value='Ingresar' />
</form>
<a href='/register'>Registrarse</a`);
});
Then I have a Post method in which I set the cookies:
app.post("/login", (req, res) => {
const { email, password } = req.body;
const user = users.filter(
(e) => e.email === email && e.password === password
);
if (user.length >= 1) {
res.cookie("userId", user.id);
res.cookie("password", user.password);
res.redirect("/home");
} else {
console.log("contraseña incorrecta");
res.redirect("/login");
}
});
The problem is that when I go to this route, the user.name and user.email are undefined. In other words, I can´t acces to the cookie:
app.get("/home", (req, res) => {
const id = req.cookies.userId;
console.log(id); //this is undefined
const user = users.filter((u) => u.id === id);
//console.log(user);
res.send(`
<h1>Bienvenido ${user.name}</h1>
<h4>${user.email}</h4>
<a href='/'>Inicio</a>
`);
});
Advices?
Here is the complete code:
const express = require("express");
const morgan = require("morgan");
const cookieparser = require("cookie-parser");
const bodyparser = require("body-parser");
const app = express();
const users = [
{ id: 1, name: "Franco", email: "Franco#mail.com", password: "1234" },
{ id: 2, name: "Toni", email: "Toni#mail.com", password: "1234" },
];
app.use(morgan("dev"));
app.use(cookieparser());
app.use(bodyparser.urlencoded({ extended: true }));
app.use((req, res, next) => {
console.log(req.cookies);
next();
});
app.get("/", (req, res) => {
res.send(`
<h1>Bienvenidos a Henry!</h1>
${
req.cookies.userId
? `<a href='/home'>Perfil</a>
<form method='post' action='/logout'>
<button>Salir</button>
</form>
`
: `
<a href='/login'>Ingresar</a>
<a href='/register'>Registrarse</a>`
}
`);
});
app.get("/register", (req, res) => {
res.send(`<h1>Registrarse</h1>
<form method='post' action='/register'>
<input name='name' placeholder='Nombre' required />
<input type='email' name='email' placeholder='Email' required />
<input type='password' name='password' placeholder='Contraseña' required />
<input type='submit' value='Registrarse' />
</form>
<a href='/login'>Iniciar sesión</a>`);
});
app.get("/login", (req, res) => {
res.send(`<h1>Iniciar sesión</h1>
<form method='post' action='/login'>
<input type='email' name='email' placeholder='Email' required />
<input type='password' name='password' placeholder='Contraseña' required />
<input type='submit' value='Ingresar' />
</form>
<a href='/register'>Registrarse</a`);
});
app.post("/login", (req, res) => {
const { email, password } = req.body;
const user = users.filter(
(e) => e.email === email && e.password === password
);
if (user.length >= 1) {
res.cookie("userId", user.id);
res.cookie("password", user.password);
res.redirect("/home");
} else {
console.log("contraseña incorrecta");
res.redirect("/login");
}
});
app.get("/home", (req, res) => {
const id = req.cookies;
console.log(id);
const user = users.filter((u) => u.id === id);
//console.log(user);
res.send(`
<h1>Bienvenido ${user.name}</h1>
<h4>${user.email}</h4>
<a href='/'>Inicio</a>
`);
});
app.listen(3000, (err) => {
if (err) {
console.log(err);
} else {
console.log("Listening on localhost:3000");
}
});
Part of your problem is that this code:
const user = users.filter(
(e) => e.email === email && e.password === password
);
produces an Array. So, user is an array.
Therefore when you do this:
res.cookie("userId", user.id);
res.cookie("password", user.password);
Both user.id and user.password are ignoring the match you got in user[0] and are referring to non-existent properties on the user array object. They will end up undefined and thus why res.cookie() is not setting a meaningful value.
You should, instead be doing this:
res.cookie("userId", user[0].id);
res.cookie("password", user[0].password);
But, please don't put a password in a user's cookie. There should be no reason to ever do that. Even more so when it's in plain text. If you want to know if the previous user is logged in or not, then use a cryptographically secure token in the cookie (like something express-session uses). Don't put their password in a cookie.

Formatting authentication request object from VueJS properly

I have a VueJS/Vuex frontend consuming an express/postgres api.
In Postman, both registration and login work with a request like:
{ "user": { "email": "user#gmail", "password":...}}
From the Vue app, registration works as expected, but for login, instead of sending a request object like
{ "user": { "email": "user#gmail", "password":...}}
, which is what the api is expecting, it is sending only,
{ "email": "user#gmail", "password":...}
This results in the api throwing:
TypeError: Cannot read property 'email' of undefined
Here is my Login component:
<template>
<div class="ui stackable three column centered grid container">
<div class="column">
<h2 class="ui dividing header">Log In</h2>
<Notification
:message="notification.message"
:type="notification.type"
v-if="notification.message"
/>
<form class="ui form" #submit.prevent="login">
<div class="field">
<label>Email</label>
<input type="email" name="email" v-model="email" placeholder="Email" required>
</div>
<div class="field">
<label>Password</label>
<input type="password" name="password" v-model="password" placeholder="Password" required>
</div>
<button class="fluid ui primary button">LOG IN</button>
<div class="ui hidden divider"></div>
</form>
<div class="ui divider"></div>
<div class="ui column grid">
<div class="center aligned column">
<p>
Don't have an account? <router-link to="/signup">Sign Up</router-link>
</p>
</div>
</div>
</div>
</div>
</template>
<script>
import Notification from '#/components/Notification'
export default {
name: 'LogIn',
components: {
Notification
},
data () {
return {
email: '',
password: '',
notification: {
message: '',
type: ''
}
}
},
// beforeRouteEnter (to, from, next) {
// const token = localStorage.getItem('tweetr-token')
// return token ? next('/') : next()
// },
methods: {
login () {
this.$store
.dispatch('login', {
email: this.email,
password: this.password
})
.then(() => {
console.log(this.$store.user)
// redirect to user home
this.$router.push('/')
})
.catch(error => console.log(error))
}
}
}
</script>
And this is my store.js:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
// import SubscriptionsService from './services/SubscriptionsService'
Vue.use(Vuex)
const VUE_APP_ROOT_API = 'http://localhost:8000'
export default new Vuex.Store({
state: {
status: '',
user: JSON.parse(localStorage.getItem('user'))
},
mutations: {
auth_request (state) {
state.status = 'Signing in...'
},
set_user (state, user) {
state.user = user
localStorage.setItem('user', JSON.stringify(user))
console.log(user)
},
auth_success (state) {
state.status = 'success'
},
auth_error (state) {
state.status = 'Invalid credentials'
},
logout (state) {
state.status = ''
state.user = null
localStorage.removeItem('user')
}
},
actions: {
register ({ commit }, user) {
return new Promise((resolve, reject) => {
commit('auth_request')
console.log(process.env.VUE_APP_ROOT_API)
axios({ url: VUE_APP_ROOT_API + '/api/auth', data: user, method: 'POST' })
.then(async resp => {
const user = resp.data.user
commit('auth_success')
commit('set_user', user)
resolve(resp)
})
.catch(err => {
commit('auth_error', err)
localStorage.removeItem('token')
reject(err)
})
})
},
login ({ commit }, user) {
return new Promise((resolve, reject) => {
commit('auth_request')
console.log(user);
axios({ url: VUE_APP_ROOT_API + '/api/auth/login', data: user, method: 'POST' })
.then(resp => {
const user = resp.data.user
// console.log(user)
// console.log(resp)
commit('auth_success')
commit('set_user', user)
resolve(resp)
})
.catch(err => {
commit('auth_error')
commit('logout')
reject(err)
})
})
},
logout ({ commit }) {
return new Promise((resolve) => {
commit('logout')
localStorage.removeItem('token')
delete axios.defaults.headers.common['authorization']
resolve()
})
}
},
getters: {
isAuthenticated: state => !!state.user,
authStatus: state => state.status,
user: state => state.user
}
})
for comparison, here is my working SignUp component:
<template>
<div class="ui stackable three column centered grid container">
<div class="column">
<h2 class="ui dividing header">Sign Up, it's free!</h2>
<form class="ui form" #submit.prevent="signup">
<div class="field">
<label>Username</label>
<input type="username" name="username" v-model="username" placeholder="Username">
</div>
<div class="field">
<label>Email</label>
<input type="email" name="email" v-model="email" placeholder="Email">
</div>
<div class="field" >
<label>Password</label>
<input type="password" name="password" v-model="password" placeholder="Password">
</div>
<button class="fluid ui primary button">SIGN UP</button>
<div class="ui hidden divider"></div>
</form>
<div class="ui divider"></div>
<div class="ui column grid">
<div class="center aligned column">
<p>
Got an account? <router-link to="/login">Log In</router-link>
</p>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SignUp',
data () {
return {
email: '',
password: '',
username: '',
notification: {
message: '',
type: ''
}
}
},
methods: {
signup: function () {
let data = {
user: {
email: this.email,
password: this.password,
username: this.username
}
}
this.$store.dispatch('register', data)
.then(() => this.$router.push('/'))
.catch(err => console.log(err))
},
}
}
</script>
How do I format the request object to match what the api expects?
Try sending the payload in a similar structure you have for your sign up function:
.dispatch('login', {
user: {
email: this.email,
password: this.password
}
})

Can not get header token in middleware

When I sign up a user, the header gets set in the /signup route.
Header token set successfully
But when I try to access the header on / route. The authorization fails because in auth.js, getting the header with const token = req.header('curToken') returns undefined. In the network log I can see that the header that has been set (curToken) is empty or non-existent, but is allowed. Can not get Header token
// index.js
const express = require('express')
require('./db/mongoose')
const userRouter = require('./routers/user')
const app = express()
const port = process.env.PORT || 3000
const cors = require('cors')
app.options('*', cors())
app.use(cors())
app.use(express.json())
app.use(userRouter)
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
// user.js (express route)
const express = require('express')
const User = require('../models/user')
const auth = require('../middleware/auth')
const router = new express.Router()
// signup
router.post('/signup', async (req, res) => {
const user = new User(req.body)
try {
await user.save()
const token = await user.generateAuthToken()
res.set('curToken', token) // set header
console.log('registered')
res.send({ user, token })
} catch(err) {
res.status(400).send(err)
}
})
// test if token header is accesible
router.get('', auth, async (req, res) => {
try {
// const users = await User.find({})
res.send("logged in.")
} catch(err) {
res.send(err)
}
})
module.exports = router
// auth.js middleware
const jwt = require('jsonwebtoken')
const User = require('../models/user')
const auth = async (req, res, next) => {
res.header('Access-Control-Expose-Headers', 'curToken')
try {
const token = req.header('curToken') // get header
console.log('auth token:', token) // header returns undefined
const decoded = jwt.verify(token, 'thisismysecretcode')
const user = await User.findOne({ _id: decoded._id, 'tokens.token': token })
if (!user) {
throw new Error()
}
req.token = token
req.user = user
next()
} catch(err) {
res.status(401).send({error: 'Please authenticate.'})
}
}
module.exports = auth
// Sign Up
<template>
<div>
SignUp
<form #submit="sendRegData" #submit.prevent>
<input type="text" v-model="firstName" name="firstName" placeholder="First name"><br>
<input type="text" v-model="lastName" name="lastName" placeholder="Last name"><br>
<input type="text" v-model="email" name="email" placeholder="Email"><br>
<input type="text" v-model="password" name="password" placeholder="Password"><br>
<input type="submit" value="Send">
</form>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: "SignUp",
data() {
return {
firstName: null,
lastName: null,
email: null,
password: null
}
},
methods: {
async sendRegData() {
try {
await axios.post('http://localhost:3000/signup', {
firstName: this.firstName,
lastName: this.lastName,
email: this.email,
password: this.password
}).then((res) => {
let token = res.data.token
// console.log('token res received in front:', token)
// localStorage.setItem("currentToken", token)
// console.log('curToken:', localStorage.getItem("currentToken"))
})
} catch(err) {
console.log(err)
}
}
}
};
</script>
// login
<template>
<div class="home">
<!-- <h1>{{ User.firstName }}</h1> -->
</div>
</template>
<script>
import axios from 'axios';
export default {
name: "Page",
data() {
return {
Users: {},
dataFetched: false
}
},
async mounted() {
try {
this.Users = await axios.get('http://localhost:3000/')
console.log(this.Users)
// this.User = this.User.data[0] // transform first object from array
// this.dataFetched = true
} catch(err) {
console.error(err)
}
}
};
</script>