Setting and retrieving session works in Postman but not working in browser - javascript

I am working with this NodeJS project using express-session to create session for my application. The problem is, when I make a post request to the http://localhost:5500/login, a session is created with additional property userid that I added intentionally. Then, when I use Postman to make a get request to http://localhost:5500/, the application actually receives the session with the property userid and redirect the user to his home page based on the userid is set or not. However, if I make get request to http://localhost:5500/ from a browser like Chrome, my server is not able to get the session with the additional property `userid' that I added when log in successfully and does not redirect my user to his home page. Can anyone explain why this happens please? Thank you
Here is the code of my index.js
`
const express = require("express")
const app = express()
const PORT = process.env.PORT || 5500
const session = require("express-session")
const { routers } = require("./routes/routes")
const mongoose = require("mongoose")
const cookieParser = require("cookie-parser")
const TIME = 1000 * 60 * 5
app.use(cookieParser())
app.use(
session({
secret: "iamnamdo1234567",
saveUninitialized: true,
cookie: { maxAge: TIME, sameSite: "strict" },
resave: false
})
)
const URI = process.env.DB_CONNECTION
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
app.use("/api", routers)
app.get("/", (req, res) => {
let session = req.session.userid
session ? res.status(200).send("Hello my friend, you are logged in") : res.status(400).send("You need to log in")
})
mongoose.connect(URI, { useNewUrlParser: true.valueOf(), useUnifiedTopology: true }, err => {
if (err) {
console.log(err)
} else {
console.log("database connected")
}
})
app.listen(PORT, () => {
console.log(`Go to http://localhost:${PORT}`)
})
`
This is the code of my routes.js
`
const express = require("express")
const route = express.Router()
const { User } = require("../models/User")
const bcrypt = require("bcrypt")
const errorHandler = (type, error) => {
if (type === "register") {
if (error.code === 11000) {
return { message: "Username has been taken" }
} else if (error._message === "User validation failed") {
return { message: error.errors.username?.properties.message || error.errors.password?.properties.message }
}
} else if (type === "login") {
return { message: `${error}` }
}
}
route.post("/register", async (req, res) => {
try {
const { username, password } = req.body
const user = await User.create({ username, password })
res.status(200).send("User has been created successfully")
} catch (error) {
// console.log(error)
let message = errorHandler("register", error)
res.status(400).send(message)
}
})
route.post("/login", async (req, res) => {
const { username, password } = req.body
try {
const user = await User.findOne({ username })
if (!user) {
throw (new Error().message = "Username not found")
}
const checkPassword = await bcrypt.compare(password, user.password)
if (checkPassword === false) {
throw (new Error().message = "Password is incorrect")
} else {
req.session.userid = user.username
console.log(req.session.userid)
res.status(200).send("Logged in")
}
} catch (error) {
let message = errorHandler("login", error)
res.status(400).send(message)
}
})
route.post("/logout", (req, res) => {
req.session.destroy()
res.redirect("/")
})
module.exports.routers = route
`
I tried to access the session when making get request from the browser

If the session details are visible in Postman but not in the browser, it could be due to a number of reasons, one of them is Cookie policy.
By default, cookies are only sent with requests made to the same origin as the current page. To send cookies with cross-origin requests, you need to set the withCredentials option in Axios. Try this it worked for me
const axios = require('axios');
axios.defaults.withCredentials = true;

Related

User is not authenticated jswtoken

I have created a login page and a about page the user will only access the about page if the user is logged in.
I am trying to authenticate the user by using the tokens generated while signing in, but the token is not getting authenticated even after signing in with the correct credentials. I don't know what is the problem?
This is code to my sign-in and token generating method
const express = require("express");
const { default: mongoose } = require("mongoose");
const router = express.Router();
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
require("../db/conn");
const User = require("../model/userSchema");
const cookieParser = require('cookie-parser');
const Authenticate = require("../middleware/authenticate");
router.use(cookieParser());
//LOgin route
router.post("/signin", (req, res)=>{
if(!req.body.email || !req.body.password){
return res.status(400).json({error: "Plz fill the required data"});
}else{
bcrypt.hash(req.body.password, 12, function (err, hash) {
User.findOne({email: req.body.email}, function (err, foundUser) {
if(err){
console.log(err);
}else{
if(foundUser){
bcrypt.compare(req.body.password, foundUser.password, function (err, result) {
if(result){
return res.json({message: "successfully log in"})
}else{
return res.json({message: "incorrect password"});
}
});
const email = req.body.email;
const token = jwt.sign(
{ user_id: foundUser._id, email },
process.env.TOKEN_KEY,
{
expiresIn: "720h",
}
);
foundUser.tokens = foundUser.tokens.concat({token: token});
foundUser.save();
// res.status(200).json(foundUser);
console.log(foundUser);
}else{
return res.status(400).json({message: "user not found"});
};
}
})
})
}
});
//about us page
router.get("/about", Authenticate, function (req, res) {
console.log("about running");
res.send(req.rootUser);
});
module.exports = router;
this is the code to authenticate the user
require("dotenv").config({path: "./config.env"});
const jwt = require("jsonwebtoken");
const User = require("../model/userSchema");
const Authenticate = async(req, res, next) =>{
try {
const token = req.cookies.jwtoken;
const verifyToken = jwt.verify(token, process.env.TOKEN_KEY);
const rootUser = await User.findOne({ _id: verifyToken._id, "tokens.token": token});
if(!rootUser) {
throw new Error("User not found")
}
req.token = token;
req.rootUser = rootUser;
req.userID = rootUser._id;
next();
} catch (err) {
console.log(err);
return res.status(401).send("Unauthorized: No token provided");
}
}
module.exports = Authenticate;
This is react based code of: About-page to display it or not based on user's authenticity.
const navigate = useNavigate();
const callAboutPage = async() =>{
try {
const res = await fetch("/about",{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type" : "application/json"
},
credentials: "include"
});
const data = await res.json();
console.log(data);
if(!res.status === 200){
const error = new Error(res.error);
throw error;
}
} catch (err) {
console.log(err);
navigate("/login");
}
}
As said in the comment looks like there is a issue on the process for setting up the jwtoken, and when you sign in, you just need to find the user and compare the password, there is no need to do the hash with Bcrypt, since you're not registing new user, for example, i will use Async/await instead of callback function, in order for you to read it much more easier:
//Login route
router.post("/signin", async (req, res)=> {
const { reqEmail, reqPassword } = req.body; //destructuring so less thing to write at the next step
if(!reqEmail || !reqPassword) {
return res.status(400).json({message: "Plz fill the required data"});
}
try {
const foundUser = await User.findOne({email: reqEmail})
if(!foundUser) {
return res.status(400).json({message: "Wrong username or password!"})
}
const result = await bcrypt.compare(reqPassword, foundUser.password);
if(!result){
return res.json({message: "Wrong username or password!"})
} else {
const accessToken = jwt.sign(
{ user_id: foundUser._id, email: foundUser.email},
process.env.TOKEN_KEY,
{ expiresIn: "720h",}
);
// I am confuse what are you trying to do here, in your place I would set up on the cookie since you do that on your authentification.
res.cookie("jwt", accessToken, {
maxAge: 60000, // 60 sec for testing
httpOnly: true,
sameSite: false, //false only for dev
secure: false, //false only for dev
})
res.status(200).json(foundUser);
};
} catch (error) {
return res.status(500).json({message: `${error}`})
}
Than the authentification middleware :
// ...
const Authenticate = (req, res, next) => {
const accessToken = req.cookies.jwt
if(!accessToken) {
return res.status(401).json({error: "Unauthorized: No token provided"});
}
try {
const user = jwt.verify(accessToken, process.env.TOKEN_KEY)
if(user) {
req.user = user
return next();
}
} catch (error) {
return res.status(403).json({error: "Forbidden token error"})
}
}
about page component it's simple for now since you don't manage any state
const navigate = useNavigate();
const callAboutPage = async() =>{
try {
const res = await fetch("/about",{
headers: {
"Content-Type": "application/json"
},
credentials: "include"
});
if(res.status === 200){
const data = await res.json();
// set up the state for rendering
console.log(data);
} else {
// you can also create a state to catch the error message from the backend, in this case the response json should be move to above the if statement.
throw new Error("You must log in to get access")
// than you can display this error message, or from the backend using state for this bloc, and the catch bloc
// navigate to /login
}
} catch (err) {
console.log(err);
navigate("/login");
}
}
router.use(cookieParser());
Try to use cookieParser with app.use instead. (app from express instense)
Expample:
const app = express();
app.use(cookieParser());
and try to put it before server listening in index.js or app.js file.
Hope it help.

"Cannot set headers after they are sent to the client" for private routes after logging in JWT NodeJS

I am working on a backend for a Online mediconsult app and I came across this error in the JWT authentication. Since I am a newbie I dunno much about this topic. I have this 3 routes on my NodeJS /register, /login, /appointments. I was able to hit "/register" and "/login" perfectly fine. But when I copy the JWT token generated by "/login" route and paste it 'authorization' header it throws the problem.
node:internal/errors:484
ErrorCaptureStackTrace(err);
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:393:5)
at ServerResponse.setHeader (node:_http_outgoing:644:11)
at ServerResponse.header (C:\Users\krish\Desktop\mrcooper-task\server\node_modules\express\lib\response.js:794:10)
at ServerResponse.send (C:\Users\krish\Desktop\mrcooper-task\server\node_modules\express\lib\response.js:174:12)
at module.exports.login (C:\Users\krish\Desktop\mrcooper-task\server\controllers\authController.js:62:7) {
code: 'ERR_HTTP_HEADERS_SENT'
}
Node.js v18.12.0
A strange thing is, when I restart the server again with the same auth token, it works!.
Wonder why would it hit the above error before restarting ?
Code
index.js
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const app = express();
require('dotenv').config();
//External routes
const authRoutes = require("./routes/authRoutes");
const appointRoutes = require("./routes/appointRoutes");
// Middlewares
app.use(cors());
app.use(express.json());
//DB connection
const dbURI =
process.env.DB_URL;
mongoose
.connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true })
.then((result) =>
app.listen(8080, () =>
console.log("App sucessfully started on localhost port 8080")
)
)
.catch((err) => console.log(err));
//Internal routes
app.use(authRoutes);
app.use(appointRoutes);
appointRoutes.js
const { Router } = require("express");
const verify = require("./verifyToken")
const router = Router();
router.get("/appointments",verify, (req, res) => {
res.send({ message: "Appointment route" });
});
module.exports = router;
authRoutes.js
const { Router } = require("express");
const User = require("../models/User");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const { registerValidator, loginValidator } = require("../validation");
const router = Router();
router.post("/register", async (req, res) => {
//Validate data before creating a user
const { error } = registerValidator(req.body);
if (error) {
return res.status(400).send(error.details[0].message);
}
//Check if email already exists
const emailExists = await User.findOne({ email: req.body.email });
if (emailExists) {
return res.status(400).send("Email already exists");
}
const { name, email, password, catogery, DOB } = req.body;
//Hash password
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
//console.log(hashedPassword);
try {
const user = await User.create({
name,
email,
password: hashedPassword,
catogery,
DOB,
});
res.status(201).json({ user: user._id });
} catch (err) {
//console.log(err);
res.status(400).send(err);
}
});
router.post("/login", async (req, res) => {
const { email, password } = req.body;
//Validate data before authenticating a user
const { error } = loginValidator(req.body);
if (error) {
return res.status(400).send(error.details[0].message);
}
//Check if email dosen't exists
const user = await User.findOne({ email: req.body.email });
if (!user) {
return res
.status(400)
.send("Email dosen't exists. Please register and try again");
}
//Passowrd is incorrect
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) return res.status(400).send("Invalid Passowrd");
//Create and assign JWT token
const token = jwt.sign({_id: user._id}, process.env.TOKEN_SECRET)
res.header('auth-token', token).send(token);
//console.log(email, password);
res.send("Logged In!");
});
module.exports = router;
Here's what I did
I did few googles and searches on this error and found out that this error mainly throws out when we return multiple response per cycle. I checked the code below and I did'nt see multiple response coming from neither /login route nor /appointments route. Would there be any response leaks from if conditions accidentaly?
When I exit from nodemon and start again with the same take generated, now it can hit the /appointment. I wonder how it works ?
You get error when function like this
if(statement){
res.send(something)
}
res.send(something)
because code is continue after res.send() function
You must fix it to
if(statement){
return res.send(something)
}
return res.send(something)
and your res.send function in authController.js:62:7

GET information from user in database

I am making full stack app and learn from tutorials and videos . I have a problem with GET request to get information about user which is login in the system. I use Postman to check the requests. When I add user with /login , the Postman look user's accesstoken code. I copy his code and paste it in authorization key in headers in Postman and when I change the URL in localhost to /infor to get information about this user and send it. But it say me "Invalid Authentication". I can't find the wrong. I think the problem is in controllers/userCtrl.js in getUser function. Can you help me?
I put the code:
server.js
require('dotenv').config()
const express = require('express')
const mongoose = require('mongoose')
const cors = require('cors')
const fileUpload = require('express-fileupload')
const cookieParser = require('cookie-parser')
const app = express()
app.use(express.json())
app.use(cookieParser())
app.use(cors())
// Use temp files instead of memory for managing the upload process.
app.use(fileUpload({
useTempFiles: true
}))
// Routes
app.use('/user', require('./routes/userRouter'))
// Connect to Mongodb
const URL = process.env.MONGO_URL
mongoose.connect(URL,{
useCreateIndex: true,
useFindAndModify: false,
useNewUrlParser: true,
useUnifiedTopology: true
}, err =>{
if(err) throw err;
console.log('Connected to MongoDB')
})
const PORT = process.env.PORT || 5000
app.listen(PORT, () => {
console.log('Server is running on port', PORT)
})
.env
MONGO_URL = ***********
ACCESS_TOKEN_SECRET = ***********
REFRESH_TOKEN_SECRET = *************
routes/userRouter.js
require('dotenv').config()
const express = require('express')
const mongoose = require('mongoose')
const cors = require('cors')
const fileUpload = require('express-fileupload')
const cookieParser = require('cookie-parser')
const app = express()
app.use(express.json())
app.use(cookieParser())
app.use(cors())
// Use temp files instead of memory for managing the upload process.
app.use(fileUpload({
useTempFiles: true
}))
// Routes
app.use('/user', require('./routes/userRouter'))
// Connect to Mongodb
const URL = process.env.MONGO_URL
mongoose.connect(URL,{
useCreateIndex: true,
useFindAndModify: false,
useNewUrlParser: true,
useUnifiedTopology: true
}, err =>{
if(err) throw err;
console.log('Connected to MongoDB')
})
const PORT = process.env.PORT || 5000
app.listen(PORT, () => {
console.log('Server is running on port', PORT)
})
models/userModel.js
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true,
},
role: {
type: Number,
default: 0
},
cart: {
type: Array,
default: []
}
}, {
timestamps: true
})
module.exports = mongoose.model('Users', userSchema)
middleware/auth.js
const jwt = require('jsonwebtoken')
const auth = (req, res, next) => {
try{
const token = req.header("Authorization")
if(!token) return res.status(400).json({ msg: "Invalid Authentication" })
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
if(!err) return res.status(400).json({msg: "Invalid Authentication" })
req.user = user
next()
})
} catch (err) {
return res.status(500).json({msg: err.message})
}
}
module.exports = auth
controllers/userCtrl.js
const Users = require('../models/userModel')
const bcrypt = require('bcrypt')
const jwt = require('jsonwebtoken')
const userCtrl = {
register: async (req, res) => { // async before a function means one simple thing: a function always returns a promise.
try{
const { name, email, password } = req.body
const user = await Users.findOne({ email }) // wait until the promise resolves
if(user) return res.status(400).json({msg: "The email already exists"})
if(password.length < 6)
return res.status(400).json({msg: "Password is at least 6 characteres long."})
//Password encryption
const passwordHash = await bcrypt.hash(password, 10)
const newUser = new Users({
name, email, password: passwordHash
})
// save mongodb
await newUser.save()
//then create jsonwebtoken to authentication
const accesstoken = createAccessToken({ id: newUser._id })
const refreshtoken = createRefreshToken({ id: newUser._id })
res.cookie('refreshtoken', refreshtoken, {
httpOnly: true,
path: '/user/refresh_token'
});
res.json({accesstoken})
} catch(err){
return res.status(500).json({msg: err.message})
}
},
login: async (req, res) => {
try{
const {email, password} = req.body;
const user = await Users.findOne({email})
if(!user) return res.status(400).json({msg: "User does not exist."})
const isMatch = await bcrypt.compare(password, user.password)
if(!isMatch) return res.status(400).json({msg: "Incorrect password"})
// if login success, create access token and refresh token
const accesstoken = createAccessToken({ id: user._id })
const refreshtoken = createRefreshToken({ id: user._id })
res.cookie('refreshtoken', refreshtoken, {
httpOnly: true,
path: '/user/refresh_token'
});
res.json({accesstoken})
} catch(err){
return res.status(500).json({msg: err.message})
}
},
logout: async (req, res)=> {
try{
res.clearCookie('refreshtoken', {path: '/user/refresh_token'})
return res.json({msg: "Logged out"})
}catch(err){
return res.status(500).json({msg: err.message})
}
},
refreshToken: (req, res) => {
try{
const rftoken = req.cookies.refreshtoken
if(!rftoken) return res.status(400).json({msg: "Please login or Register"})
jwt.verify(rftoken, process.env.REFRESH_TOKEN_SECRET, (err, user) => {
if(err) return res.status(400).json({msg: "Please login or Register"})
const accesstoken = createAccessToken({id: user.id})
res.json({ accesstoken })
})
}catch (err) {
return res.status(500).json({msg: err.message})
}
},
getUser: async (req, res) => { // problem
try{
const user = await (await Users.findById(req.user.id)).isSelected('-password')
if(!user) return res.status(400).json({ msg: "Useer does not exist."})
res.json(req.user)
}catch (err) {
return res.status(500).json({msg: err.message})
}
}
}
const createAccessToken = (user) => {
return jwt.sign(user, process.env.ACCESS_TOKEN_SECRET, { expiresIn: '1d' })
}
const createRefreshToken = (user) => {
return jwt.sign(user, process.env.REFRESH_TOKEN_SECRET, { expiresIn: '7d' })
}
module.exports = userCtrl
For your middle ware for getting the token (auth function)
const { authorization } = req.headers
if (!authorization) {
console.log('[No Authorization Code]');
return res.status(401).send({ message: 'Unauthorized' });
}
if (!authorization.startsWith('Bearer')) {
console.log('[Authorization need to start with Bearer]')
return res.status(401).send({ message: 'Unauthorized' });
}
const split = authorization.split('Bearer ')
if (split.length !== 2) {
console.log('[Invalid Authorization Param')
return res.status(401).send({ message: 'Unauthorized' });
}
const token = split[1] //this is your token to use with jwt.verify
When you sending the token in postman, select Bearer Token
When you start creating your frontend, the codes should be equivalent to the following fetch request
fetch('/api/path', { method: 'GET', headers: { "Authorization": `Bearer ${token}`}}).(res => res.json())
May change method to your desire method (e.g get or post), and the token will be the the jwt token

Why cookieParser doesnt return value?

I'm using vue, vue-router for my client-side and express, morgan for my server side (MEVN app)
So, at the client i'm setting cookies by using vue-cookies
this.$cookies.set('Login', this.login, new Date(Date.now() + 86400 * 5 * 1000))
this.$cookies.set('Password', this.password, new Date(Date.now() + 86400 * 5 * 1000))
And at the server side i'm using cookieParser
So, at app.js i have such a code
const express = require('express');
const morgan = require('morgan');
const cors = require('cors');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const config = require('./config/config');
const db = require('./controllers/DB');
const mCLogs = require('./modelControllers/Logs');
const mCLogin = require('./modelControllers/Login');
const app = express();
app.use(morgan('combined'));
app.use(bodyParser.json());
app.use(cors());
app.use(cookieParser()); /*cookie parser*/
And, at the file ./modelControllers/Login i have such a code for a GET request
exports.checkLoginSession = async (req, res, next) => {
/*its not all of the code*/
var loginHash = req.cookies['Login'];
console.log(loginHash)
if(loginHash == undefined) {
res.send({
logged: false,
description: "err mes"
});
} else {
res.send({
logged: true,
description: "mes"
});
}
}
and the problem is that the var loginHash = req.cookies['Login']; always return undefined, even when i have "Login" cookie
Addition:
How i call this method:
Client-side and using axios
mounted () {
this.getLoginData()
},
methods: {
async getLoginData () {
const response = await LoginHandler.checkUserLoginSession()
if (response.data.logged === true) {
this.$router.push('/')
} else {
this.errorMessage = response.data.description
}
}
}
LoginHandler.js(client side)
import api from '#/services/api'
export default {
checkUserLoginSession () {
return api().get('/login')
}
}
Server-side /login link in app.js
app.get('/login', mCLogin.checkLoginSession);
app.post('/login', mCLogin.checkUserData);
ADDITION:
It doesnt work when i use such a code with axios API:
import api from '#/services/api'
export default {
checkUserLoginSession () {
return api().get('/login')
}
}
So, when i call checkUserLoginSession app.get('/login') return cookie value undefined, but, if i open link in browser (serverside) localhost:3000/login it's returning correct value
Addition: checkUserData
exports.checkUserData = async (req, res) => {
try {
let login = req.body.login;
let password = req.body.password;
const user = await db.users.findOne({
where: {
Login: login,
Password: password
}
});
if(user == null)
{
res.send({
logged: false,
description: "Пользователь не найден."
});
return;
}
if(user.dataValues.Login == login && user.dataValues.Password == password)
{
res.send({
logged: true,
description: "Авторизация произошла успешно. Сейчас Вас перенаправит!"
});
return;
}
}
catch(ex) {
res.send({
logged: false,
description: "Произошла ошибка на стороне сервера."
});
console.log(ex);
return;
}
}
If i add withCredentials: true to axios.create, server return cookie value, but i've this errors on console line
Access to XMLHttpRequest at 'http://localhost:3000/login' from origin 'http://localhost:8080' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
Ok guys, i solve my issue.
So, the answer is.
Change LoginHandler code:
From:
import api from '#/services/api'
export default {
checkUserLoginSession () {
return api().get('/login')
}
}
To:
import api from '#/services/api'
export default {
checkUserLoginSession () {
return api().get('/login', {withCredentials: true})
}
}
Change app.js
From:
app.use(cors());
To:
app.use(cors({ credentials: true, origin: "http://localhost:8080" }));
Change method checkLoginSession
To:
exports.checkLoginSession = (req, res, next) => {
const { Login, Password } = req.cookies;
//Where Login, Password ... is your cookie name
//console.log(Login)
if(Login == undefined) {
res.send({
logged: false,
description: "Нет сохранённых хешей для авторизации!"
});
} else {
res.send({
logged: true,
description: "Авторизован."
});
}
}
P.S Thanks to all, who tried to help me

Restful API: How to display specific data in Node/Express app?

I am building a simple Node/Express app to login a user. Before user can login the app must check if the email provided exists in the database.
The structure of my app is like this:
* db/data.js
* app.js // server
I want to login a user
const data = [
{
id: 1,
email: 'xyz#xyz.com',
fist_name: 'hekw',
last_name: 'xyz',
password: 'usr$#',
},
];
export default data;
import express from 'express';
import bodyParser from 'body-parser';
import data from './db/data';
// set up the express app
const app = express();
// Parse incoming requests data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
/**
* Sign in a user
* #param {object} req
* #param {object} res
*/
app.post(`/login`, (req, res) => {
const findUserByEmail = (email) => {
for (let i = 0; i < data.length; i++) {
return data[i]['email'] === email ? true : false;
}
};
if (findUserByEmail(req.body.email)) {
return res.status(409).send({
success: false,
message: 'email already exists',
//findUserByEmail(req.body.email)
//data,
});
}
const port = 5000;
app.listen(port, () => {
// console.log(`The server running on port ${PORT}`);
});
export default app;
I tried but I couldn't display info of a signed user. How can I achieve it?
This is what I need:
"status":"success"
"data": {
"id": 1,
"email":"xyz#xyz.com",
"first_name": "hekw",
"last_name": "xyz",
"password": "usr$#"
}
Edit
I've implemented the code below, but I want now to check for both email and password.
const findUserByEmail = (email) => data.find(user => user.email === email);
const foundUser = findUserByEmail(req.body.email);
if (!foundUser) {
return res.status(404).send({
status: 'error',
error: 'user does not exist, register first',
});
}
if (foundUser) {
// if password OK then diplay success message. How do I access pwd field here?
return res.status(200).send({
status: 'success',
data: foundUser,
});
}
First of all, I highly recommend using the MVC pattern and create a model for each separate data model. Also, an encryption method such as Bcrypt to encrypt the passwords before storing them to the database and using a token-based approach to handle user authentication.
For the purpose of the example, I provide a solution with the JWT and Bcrypt to help understand the process better, also for people who are looking for a more detailed answer. We can pass a middleware into routes to check the user is authenticated or not then fetch the proper data for the user.
const express = require('express');
const app = express();
const router = express.Router();
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
// This user model can be replaced with your data file, in your sample
const User = require('../models/userModel');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json()); // Always return JSON for the rest api
// Awlays set headers to controll the access
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');
return res.status(200).json({});
}
next();
});
// This is the user controller, below return it inside the route
const loginUserController = (req, res) => {
User.findOne({ email: req.body.email }) // find just one record by the email received from the user
.exec() // Use this to make a promise
.then(user => {
if (user.length < 1) { // check if the user found
return res.status(401).json({ // Check if email is not valid
message: 'Authentication Failed! Wrong login information used!'
})
}
// If status code is not 401 and user is found, then compare the password with DB version and pass "err" and "success" parameters
// user.password is the db password
bcrypt.compare(req.body.password, user.password, (err, success) => {
if (err) {
return res.status(401).json({
message: 'Authentication Failed! Wrong login information used!'
})
}
if (success) {
// Then we sign JWT if password matched
// process.env.JWT_KEY is our server jwt token
const token = jwt.sign({
email: user.email,
userId: user._id
}, process.env.JWT_KEY, {
expiresIn: '2d' // we can set the expire date (see th e docs for more info)
});
// Finally we return our token to store into user's browser cookie
// or we can just return the data, but its better to use jwt token and use it everywhere you want to get user data
return res.status(200).json({
message: 'Welcome to My App!',
data: user
token
});
}
// Here we return another 401 if the were no err or success
res.status(401).json({
message: 'Authentication Failed! Wrong login information used!'
})
})
})
.catch(err => {
// Use can create an error controller and put a switch inside of it to check response status code then return proper message
errorController(req, res, res.status, 'ANY');
})
}
// Finally we use our router to post and return login controller
router.post('/login', (req, res) => {
return loginUserController(req, res);
});
app.listen(process.env.PORT || 3000);
There are more advanced configurations, but for simplicity of the example, I provided a simple way to do the correct way (in my opinion). Hope it help.
Packages used in this example
jsonwebtoken
Bcrypt
Your code is not working. Following will not find the user object in your data array.
const findUserByEmail = (email) => {
for (let i = 0; i < data.length; i++) {
return data[i]['email'] === email ? true : false;
}
};
You can find the user like this:
const findUserByEmail = (email) => data.find((datum) => datum.email === email);
Assuming you are sending a POST request with email set correctly. You can use the following code to achieve the result you want:
const findUser = (email, pass) => data.find((datum) => datum.email === email && datum.password === pass);
let foundUser = findUser(req.body.email, req.body.password);
if (foundUser) {
return res.status(200).json({
"status":"success"
"data": foundUser
});
}
res.status(404).json({
"status": "Not Found"
"data": foundUser
});

Categories

Resources