I am following a tutorial on Udemy and creating a react app using node and express. I am losing my session and being sent back to the login page on refresh. The instructors app stays in session on refresh. Could bad routing be causing this issue? I'll provide auth.js file from my routing folder. I can add more if needed.
<<< SERVER.JS file >>>
const express = require('express');
const connectDB = require('./config/db');
const app = express();
// CONNECT To Database
connectDB();
// Init Middleware
app.use(express.json({extended: false}))
app.get('/', (req, res) => res.send('Well, hello there!'));
app.use('/api/posts', require('./routes/api/posts'));
app.use('/api/users', require('./routes/api/users'));
app.use('/api/auth', require('./routes/api/auth'));
app.use('/api/profile', require('./routes/api/profile'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`server is listening on port ${PORT}`));
<<< middleware >>>
const jwt = require('jsonwebtoken');
const config = require('config');
module.exports = function(req, res, next) {
// Get token from header
const token = req.header('x-auth-token');
// Check if not token
if (!token) {
return res.status(401).json({ msg: 'No token, authorization denied' });
}
// Verify token
try {
const decoded = jwt.verify(token, config.get('jwtSecret'));
req.user = decoded.user;
next();
} catch (err) {
res.status(401).json({ msg: 'Token is not valid' });
}
};
just in case my here is my auth.js file from routing folder
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const auth = require('../../middleware/auth');
const jwt = require('jsonwebtoken');
const config = require('config');
const { check, validationResult } = require('express-validator');
const User = require('../../models/User');
// #route GET api/auth
// #desc Test route
// #access Public
router.get('/', auth, async (req, res) => {
try {
const user = await User.findById(req.user.id).select('-password');
res.json(user);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});
// #route POST api/auth
// #desc Authenticate user & get token
// #access Public
router.post(
'/',
[
check('email', 'Please include a valid email').isEmail(),
check('password', 'Password is required').exists()
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { email, password } = req.body;
try {
let user = await User.findOne({ email });
if (!user) {
return res
.status(400)
.json({ errors: [{ msg: 'Invalid Credentials' }] });
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res
.status(400)
.json({ errors: [{ msg: 'Invalid Credentials' }] });
}
const payload = {
user: {
id: user.id
}
};
jwt.sign(
payload,
config.get('jwtSecret'),
{ expiresIn: 360000 },
(err, token) => {
if (err) throw err;
res.json({ token });
}
);
} catch (err) {
console.error(err.message);
res.status(500).send('Server error');
}
}
);
module.exports = router;
Related
I was building authentication for a website
and the req.cookie was returning undefined. Can I know what's wrong with that?
this is my server code
and I imported the auth file here
app.get("/", auth, (req, res) => {
res.render("index")
})
this is my auth.js file
const jwt = require("jsonwebtoken")
const Register = require("../models/registration")
const cookieParser = require("cookie-parser")
const express = require("express")
const app = express()
app.use(cookieParser())
const auth = async (req, res, next) => {
try {
const token = req.cookie.token_name
console.log(token)
const verifyUser = jwt.verify(token, process.env.SECRET_KEY)
next()
} catch (error) {
console.log(error)
res.status(401).send(error)
}
}
module.exports = auth
if required this is my login code as well but yeah i verified its storing cookies on the browser
app.post("/login", async (req, res) => {
try {
const password = req.body.password
const email = req.body.email
const user = await Register.findOne({ email: email })
const isMatch = await bcrypt.compare(password, user.password)
const token = await user.generateAuthenticationToken()
res.cookie('jwt', token, {
maxAge: 600*1000,
httpOnly: true,
})
if (isMatch) {
res.redirect("/")
} else {
res.send("Invalid Credentials")
}
} catch (error) {
res.status(404).send(error)
}
})
This is my index.js
import express from "express";
import router from "./routes/routes.js";
import connectDB from "./db.js";
const app = express();
connectDB();
app.use(express.json());
app.use("/", router);
app.listen(3000, () => console.log("server is running on port 3000"));
This is my jwt file which uses a middleware function on posts request
import express from "express";
import jwt from "jsonwebtoken";
import authenticateToken from "./middlewares/authenticateToken.js";
const app = express();
app.use(express.json());
app.get("/", (req, res) => res.send("Node and JWT"));
app.post("/login", (req, res) => {
const user = {
id: 1,
username: "JhonDoe",
email: "Jhon#gmail.com",
};
const token = jwt.sign(user, "secret", { expiresIn: "1day" });
res.json({ token });
});
app.post("/posts", authenticateToken, (req, res) => {
const user = req.user;
res.json(user);
});
app.listen(4000, () => console.log("server is running on port 4000"));
And this is the middleware
export default function authenticateToken(req, res, next) {
const authHeader = req.headers["authorization"];
const token = authHeader && authHeader.split(" ")[1];
console.log(token);
if (!token) {
return res.status(401).json({ msg: "No token, authorization denied" });
}
try {
const user = jwt.verify(token, "secret");
req.user = user;
next();
} catch (err) {
console.log(token);
res.status(403).json({ msg: "Token is not valid" });
}
}
But when I import it, it doesn't work correctly if I show the token in the console it shows it correctly but it returns the error "token is not valid" but if I use it below the post request in the same jwt.js file it works perfectly it show me the payload, why doesn't it work when I import it?, thanks.
Solution
Instead of
export default function authenticateToken(req, res, next) {
const authHeader = req.headers["authorization"];
const token = authHeader && authHeader.split(" ")[1];
if (!token) {
return res.status(401).json({ msg: "No token, authorization denied" });
}
try {
const user = jwt.verify(token, "secret");
req.user = user;
next();
} catch (err) {
res.status(403).json({ msg: "Token is not valid" });
}
}
this
export default function authenticateToken(req, res, next) {
const authHeader = req.headers["authorization"];
const token = authHeader && authHeader.split(" ")[1];
if (!token) {
return res.status(401).json({ msg: "No token, authorization denied" });
}
jwt.verify(token, "secret", (err, user) => {
if (err) return res.status(403).json({ msg: "Token is not valid" });
req.user = user;
next();
});
}
Documentation https://github.com/auth0/node-jsonwebtoken#readme
I am doing backend login and register project with Nodejs and Express but somehow I cannot login or register anymore or even fetch data from my usersRoute and I don't know why. I am lost..
My index.ts file:
import express from "express";
const https = require("https");
import cors from "cors";
import mongoose from "mongoose";
const app = express();
//import Routes
const usersRoute = require("./routes/users");
//Middleware
app.use(cors());
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
//Route middlewares
app.use("api/users", usersRoute);
//connect to db
mongoose
.connect("mongodb://localhost:27017/containerlab")
.then(() => {
console.log("connected to database");
})
.catch(() => {
console.log("connection failed!");
});
const PORT = 5000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
My users.ts file
import express from "express";
const router = express.Router();
const User = require("../models/User");
const {
registerValidation,
loginValidation,
} = require("../middleware/validation");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const secretKey = "f43g34gergeerg";
const verifyToken = require("../middleware/verifyToken");
//REGISTER user
router.post("/register", async (req, res) => {
//VALIDATE DATA from Joi, before register
const { error } = registerValidation(req.body);
if (error) return res.status(400).send(error.details[0].message);
//check if user is alredy in database
const emailExist = await User.findOne({ email: req.body.email });
if (emailExist) return res.status(400).send("Email already exists");
//encrypt password z bcryptjs modulom
const salt = await bcrypt.genSalt(10);
const hashPassword = await bcrypt.hash(req.body.password, salt);
//create new user
const user = new User({
email: req.body.email,
password: hashPassword,
});
try {
//save new user
const savedUser = await user.save();
//res.json(savedUser);
res.json({ user: user._id });
} catch (err) {
res.json({ message: err });
}
});
//LOGIN
router.post("/login", async (req, res) => {
//VALIDATE DATA from Joi, before register
const { error } = loginValidation(req.body);
if (error) return res.status(400).send(error.details[0].message);
//check if email exists.. če NE obstaja mail dobiš da ne ustreza
const user = await User.findOne({ email: req.body.email });
if (!user) return res.status(400).send("Email doesn't exist");
const validPass = await bcrypt.compare(req.body.password, user.password);
if (!validPass) return res.status(400).send("Invalid password");
//create and send a json web token
const token = jwt.sign({ _id: user._id }, secretKey, { expiresIn: "1h" });
res.header("auth-token", token).send(token);
res.send("Logged in!");
});
//get users
router.get("/", async (req, res) => {
try {
const users = await User.find();
res.json(users);
} catch (err) {
res.json({ message: err });
}
});
module.exports = router;
And my verifyToken.ts middleware
const jwt = require("jsonwebtoken");
const secretKey = "f43g34gergeerg";
module.exports = (req: any, res: any, next: any) => {
const token = req.header("auth-token");
if (!token) return res.status(401).send("Access denied");
try {
const verified = jwt.verify(token, secretKey);
req.user = verified;
next();
} catch (err) {
res.status(400).send("Invalid token");
}
};
Somehow I can't fetch ANY data from users.ts (from usersRoute). Thank you for your help
I am trying to hit http://localhost:5000/api/auth/ with post request using postman but it says "cannot post api/auth".
I am using mongo db and node js server.js
server.js file:
const express = require('express');
var connectDB = require('./config/db');
const app = express();
//connect database
connectDB();
// initializing middleware
app.use(express.json({extended: false}));
app.get('/', (req,res) =>
res.json({msg:'Hellow we are here'}));
//Define Routes
app.use('api/auth', require('./routes/auth'));
app.use('/api/users', require('./routes/users'));
app.use('/api/contacts', require('./routes/contacts'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log ("server running at port 5000"));
Here is the auth file:
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const {check, validationResult} = require('express-validator');
const config = require('config');
const User = require('../models/User');
//#route GET api/auth
//#desc Get logged in user
//#access private
router.get('/', (req, res)=> {
res.send('Get logged in suser');
});
//#route POST api/auth
//#desc Auth user and get token
//#access public
router.post (
'/',
[
check('email', 'Please enter a valid email').isEmail(),
check('password', 'password required').exists(),
],
async (req, res)=> {
const errors = validationResult(req);
if(!errors.isEmpty()){
return res.status(400).json({errors: errors.array()});
}
const {email , password} = req.body;
try{
let user= await User.findOne({email});
console.log(user);
if(!user)
{
return res.status(400).json({msg:"Invalid credentials"});
}
const isMatch = await bcrypt.compare(password, user.password);
if(!isMatch)
{
return res.status(400).json({msg:"Invalid credentials"});
}
const payload = {
user: { id: user.id }
};
jwt.sign(payload,
config.get('jwtSecret'),
{expiresIn: 36000},
(err, token) => {
if (err)
{ throw err;}
res.send({token});
});
}
catch (err) {
console.error(err.message);
res.status(500).send('server error');
}
});
module.exports = router;
There's a missing leading slash where you define the routes. It is
//Define Routes
app.use('api/auth', require('./routes/auth'));
but it should be
//Define Routes
app.use('/api/auth', require('./routes/auth'));
I am using JWT to generate a token for access control. I can hit /api/auth/login and get back the token, however, when attempting to hit /api/protected with a GET request, I get 401 Unauthorized.
I've looked through SO and haven't found anything specific although it seems like a routine issue, maybe. I have tried moving the route around in the server.js file to see if that is the issue . I have removed the preceeding slash from the route (from /api/protected to api/protected) and using the latter I get back a bunch of html due to, I think, the app.use(express.static....
I am using Postman to test it but i'm not sure what I'm missing here. I have also made sure to set the authorization to Bearer Token in Postman.
'use strict';
const { Strategy: LocalStrategy } = require('passport-local');
// Assigns the Strategy export to the name JwtStrategy using object destructuring
const { Strategy: JwtStrategy, ExtractJwt } = require('passport-jwt');
const { User } = require('../users/models');
const { JWT_SECRET } = require('../config');
const localStrategy = new LocalStrategy((username, password, callback) => {
let user;
User.findOne({ username })
.then(_user => {
user = _user;
if (!user) {
// Return a rejected promise so we break out of the chain of .thens.
// Any errors like this will be handled in the catch block.
return Promise.reject({
reason: 'LoginError',
message: 'Incorrect username or password'
});
}
return user.validatePassword(password);
})
.then(isValid => {
if (!isValid) {
return Promise.reject({
reason: 'LoginError',
message: 'Incorrect username or password'
});
}
return callback(null, user);
})
.catch(err => {
if (err.reason === 'LoginError') {
return callback(null, false, err);
}
return callback(err, false);
});
});
const jwtStrategy = new JwtStrategy(
{
secretOrKey: JWT_SECRET,
// Look for the JWT as a Bearer auth header
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
// Only allow HS256 tokens - the same as the ones we issue
algorithms: ['HS256']
},
(payload, done) => {
done(null, payload.user);
}
);
module.exports = { localStrategy, jwtStrategy };
'use strict';
//How does order of code affect how it works?
// YES
require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const morgan = require('morgan');
const passport = require('passport');
const path = require('path');
const { router: usersRouter } = require('./users');
const { router: authRouter, localStrategy, jwtStrategy } = require('./auth');
mongoose.Promise = global.Promise;
// Is this needed if dotenv is in this file also?
const { PORT, DATABASE_URL } = require('./config');
const app = express();
// Logging
app.use(morgan("common"));
// const logRequest = (req, res, next) => {
// const now = new Date();
// console.log(
// `local log - ${now.toLocaleDateString()} ${now.toLocaleTimeString()} ${req.method} ${req.url}`
// );
// next();
// }
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization');
res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE');
if (req.method === 'OPTIONS') {
return res.send(204);
}
next();
});
passport.use(localStrategy);
passport.use(jwtStrategy);
//app.use(logRequest);
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use('/api/users/', usersRouter);
app.use('/api/auth/', authRouter);
app.use("/api/items", require('./routes/api/items'));
// protected route that needs a valid JWT for access
const jwtAuth = passport.authenticate("jwt", { session: false });
// route to handle static content ie.e *.jpg
app.use(express.static(path.join(__dirname, "client", "build")));
app.get('/api/protected', jwtAuth, (req, res) => {
return res.json({
data: 'Hello World'
});
});
// have react client handle all additional routes
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
let server;
function runServer(DATABASE_URL, port = PORT) {
return new Promise((resolve, reject) => {
// How is DATABASE_URL used? What is the value? Is it referencing
// DATABASE_URL?
mongoose.connect(DATABASE_URL, { useNewUrlParser: true, useFindAndModify: false }, (err) => {
console.log("Success");
if (err) {
return reject(err);
}
server = app.listen(port, () => {
console.log(`Your app is listening on port ${PORT}`);
resolve();
})
.on('error', (err) => {
mongoose.disconnect();
reject(err);
});
});
});
}
function closeServer() {
return mongoose.disconnect()
.then(() => new Promise((resolve, reject) => {
console.log("Closing server");
server.close((err) => {
if (err) {
return reject(err);
}
resolve();
});
}));
}
if (require.main === module) {
runServer(DATABASE_URL)
.catch(err => console.error(err));
}
module.exports = { app, runServer, closeServer };
enter code hereI am expecting to get back a string that says "Hello World" just to make sure i'm hitting the endpoint correctly. Instead I get the 401 error, GET /api/protected HTTP/1.1" 401enter code here