///index.js
const functions = require("firebase-functions");
const express = require("express");
const app = express();
const productRouter = require('./routes/productRoutes');
const globalErrorHandler = require('./controllers/errorController');
const AppError = require('./utils/appError');
// Compressing upcompressed files which is been sent to client such text.
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'));
}
// app.use(express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
res.send('Hello World')
});
app.get('/homepage', (req, res) => {
res.send('Hello People of God')
});
app.use('/products', productRouter);
// Handing Unhandled Routes
app.all('*', (req, res, next) => {
next(new AppError(`Can't find ${req.originalUrl} on this server!`, 404));
});
app.use(globalErrorHandler);
exports.app = functions.https.onRequest(app);
///productRoutes.js
const express = require('express');
const {
getProduct,
getAllProduct,
} = require('./../controllers/productController');
const router = express.Router();
router
.route('/')
.get(getAllProduct);
router
.route('/:id')
.get(getProduct);
module.exports = router;
///productController.js
const AppError = require('../utils/appError');
const Product = require('../modals/productModels');
const catchAsync = require('../utils/catchAsync');
// GET SINGLE PRODUCT CONTROLLER
exports.getProduct = catchAsync(async (req, res, next) => {
const product = await Product.findById(req.params.id)
.populate('reviews');
if (!product) {
return next(new AppError('No product found with that ID', 404));
}
res.status(200).json({
status: 'success',
data: {
product
}
});
});
// GET ALL PRODUCT CONTROLLER
exports.getAllProduct = catchAsync(async (req, res, next) => {
const products = await Product.find();
res.status(200).json({
status: 'success',
results: products.length,
data: {
products
}
});
});
///server.js
const mongoose = require('mongoose');
const app = require('./index')
const dotenv = require('dotenv');
// CONNECTING TO MONGODB SERVER
dotenv.config({ path: './config.env' })
const DB = process.env.DATABASE.replace('<PASSWORD>', process.env.DATABASE_PASSWORD);
mongoose.connect(DB, {
useNewUrlParser: true,
safe: true,
strict: false,
useUnifiedTopology: true
}).then(con => console.log('DB connection successful'))
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`App running on port ${port}...`);
});
After running function serve on my terminal i can access the two '/' and 'homepage' app.get which return the res "Hello world" and "Hello people of God" but can't access app.use('/products', productRouter). Its does take some time to run and throw an error "{"code":"ECONNRESET"}" please why is this so.
Am expecting to get my list of products from my mongodb data base.
while submitting the post request it does not redirect me to the failureRedirect route, nor to the SuccessRedirect one, instead, the web page enters into an endless loop. Why is this happening.
It has two files
app.js:
const express = require('express');
const path = require('path');
const mongoose = require('mongoose');
const ejsmate = require('ejs-mate');
const session = require('express-session');
const flash= require('connect-flash');
const methodOverride = require('method-override');
const passport= require('passport');
const LocalStrategy= require('passport-local');
const User= require('./models/user');
const ExpressError = require('./Utilities/ExpressError');
const campgroundRoutes=require('./Routes/campgrounds');
const reviewRoutes=require('./Routes/review');
const userRoutes=require('./Routes/User');
mongoose.connect('mongodb://localhost:27017/yelp-camp');
const db = mongoose.connection;
db.on('error', console.error.bind(console, "connection error:"));
db.once('open', () => {
console.log("open connection");
});
const app = express();
app.engine('ejs', ejsmate)
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride('_method'));
app.use(express.static(path.join(__dirname, 'public')))
const sessionConfig={
secret:'thisshouldbeabettersecret',
resave: false,
saveUninitialized: true,
cookie:
{
httpOnly:true,
expires:Date.now+1000*60*60*24*7,
maxAge:1000*60*60*24*7
}
}
app.use(session(sessionConfig))
app.use(flash())
app.use(passport.initialize())
app.use(passport.session())
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser())
passport.deserializeUser(User.deserializeUser()) //deserializeUser
app.use((req, res, next) => {
res.locals.success = req.flash('success');
res.locals.error = req.flash('error');
next();
})
app.use('/',userRoutes)
app.use('/campgrounds',campgroundRoutes);
app.use('/campgrounds/:id/reviews',reviewRoutes)
app.get('/', (req, res) => {
console.log('hi on server ');
res.render('home')
});
app.all('*', (req, res, next) => {
next(new ExpressError('Page Not Found', 404));
})
app.use((err, req, res, next) => {
// { const {statusCode=500,message="SomThing went wrong "} = err;
// res.status(statusCode).send(message)
if (!err.message) err.message = "Problem Occurs Man"
res.render('Error', { err })
next();
})
app.listen(3000, () => {
console.log('listening on port 3000');
});
User.js:
const express=require('express');
const router=express.Router();
const catchAsync=require('../Utilities/catchAsync')
const User = require('../models/user');
const passport = require('passport');
// const LocalStrategy= require('passpi')
router.get('/register', (req, res) => {
res.render('users/register')
});
router.post('/register', catchAsync( async (req, res) => {
try {
const {usermail,username,userpassword}=req.body;
console.log(req.body);
const user= new User({usermail,username});
console.log(req.body);
const registerdUser= await User.register(user,userpassword);
console.log(req.body);
console.log(registerdUser);
req.flash('success','Welcome to YelpCamp');
req.redirect('/campgrounds')
} catch (err) {
req.flash('error', err.message);
res.redirect('/register')
}
}));
router.get('/login', (req, res) => {
res.render('users/login')
});
router.post('/login',passport.authenticate('local',{failureFlash: true,failureRedirect:'/login'}),(req,res) => {
req.flash('success', 'Successfully logged in!');
res.redirect('/campgrounds')
});
module.exports = router;
I have searched everywhere and tried all the available possible solutions but nothing is solving this.
I've been trying to wrap my head around this all day. I'm trying to figure out where this token is.... Any ideas?
All I keep getting is the following error and a return in text/html from my Express backend
SyntaxError: Unexpected token in JSON at position 3
index.js
const express = require("express");
const app = express();
const cors = require("cors");
var bodyParser = require("body-parser");
const dotenv = require('dotenv');
const { default: mongoose } = require("mongoose");
const auth_routes = require('./routes/auth.routes');
const rate_routes = require('./routes/rate.routes');
dotenv.config();
const port = process.env.PORT || 5000;
const mongo_uri = 'mongodb://' + process.env.MONGO_USER + ':' + process.env.MONGO_PASSWD + '#localhost:27017/home?authSource=admin';
mongoose.connect(mongo_uri)
.then((resp) => {
console.log('Connected to MongoDB');
}).catch((err) => {
console.error('Error: ', err.reason)
});
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: false,
}),
);
app.use(cors());
app.listen(port, () => { console.log("Server is running on port 5000");});
...
...
app.get('/', (req, res) => {
res.send("Welcome to the Behemoth API platform")
});
app.set('userToken', userToken);
app.use('/v1/user', auth_routes);
app.use('/v1/rates', rate_routes);
rate.routes.js - the api call
const express = require('express');
const auth_middle = require('../middleware/auth');
const axios = require("axios");
const router = express.Router();
router.route('/').get(auth_middle, async function (req, res) {
try {
let userToken = req.app.get('userToken');
const reqBody = [ {
....
....
} ];
let rateResponse = await axios.post('https://xxxxxxxx', reqBody, {
headers: {
'Authorization': 'Bearer ' + userToken
}
});
var StockRate = rateResponse.data.StockData;
res.send(rateResponse.data);
} catch (e) {
console.log(e.stack);
res.status(500).send({error: e.message + " / " + e.keyword });
}
});
module.exports = router;
auth.js
const jwt = require('jsonwebtoken');
const dotenv = require('dotenv');
dotenv.config();
module.exports = (req, res, next) => {
try {
console.log(req.headers.authorization);
const token = req.headers.authorization.split(" ")[1];
jwt.verify(token, process.env.JWT_SECRET_KEY);
next();
} catch (err) {
console.log(err);
res.send(401).json({ message: err })
}
}
I wrote a small node.js server with a login system and I am trying to protect my routes. I have created the middleware that should check authentication on each protected route, but it seems that I am not sending the JWT token correctly, because every time I log in I get the Authentication failed message. How can I send the JWT token correctly and log in if the password and username are correct? Here is my Node.js server:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();
const PORT = process.env.PORT || 1337;
const jwt = require('jsonwebtoken');
const checkAuth = require('./middleware/check-auth.js')
let Post = require('./models/post.model.js');
app.use(cors());
app.use("/assets", express.static(__dirname + "/assets"));
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view-engine', 'ejs');
app.get('/', (req, res) => {
res.render('index.ejs');
});
app.post('/', (req, res) => {
let username = req.body.username;
let password = req.body.password;
if (username !== process.env.USER_NAME && password !== process.env.USER_PASSWORD) {
res.json('Invalid credentials');
} else {
const token = jwt.sign({
username: username,
}, process.env.SECRET_KEY, {
expiresIn: '1h'
});
res.redirect(`/dashboard?token=${token}`);
}
});
app.get('/dashboard', checkAuth, (req, res) => {
res.render('dashboard.ejs');
});
app.get('/dashboard/createPost', checkAuth, (req, res) => {
res.render('post.ejs');
});
app.post('/dashboard/createPost', async (req, res) => {
let collection = connection.collection(process.env.POSTS_WITH_TAGS);
res.setHeader('Content-Type', 'application/json');
let post = new Post(req.body);
collection.insertOne(post)
.then(post => {
res.redirect('/dashboard')
})
.catch(err => {
res.status(400).send(err);
});
});
app.listen(PORT);
and here is my check-auth middleware:
const jwt = require('jsonwebtoken');
module.exports = (req, res, next) => {
try {
const token = req.headers.authorization.split(' ')[1];
console.log(token);
const decoded = jwt.verify(token, process.env.SECRET_KEY, null);
req.body.decoded = decoded;
console.log(req.body.decoded);
} catch (error) {
return res.status(401).json({
message: 'Authentication failed'
});
}
next();
};
Use Javascript fetch API for sending JWT token as header authorization
fetch('backend_domain/dashboard', {
method: 'get',
headers: {
Authorization: JWT_Token
}
}).then(data => {..your operation here..})
Reference: fetch_mdn for better understanding of fetch API
I think the problem here is that you are getting an empty object in req.body when you try to pass it as a json string in postman. I would recommend either
pass your credentials in x-www-form-urlencoded tag in postman or
Using express.Router() and creating different files for routes
In your index.js file write:
app.use('/', require('./routes.js'))
And create a file with name routes.js and put your routes as this:
const express = require('express');
const router = express.Router();
router.post('/', (req, res) => {
let username = req.body.username;
let password = req.body.password;
console.log(req.body);
if (username !== process.env.USER_NAME && password !== process.env.USER_PASSWORD) {
res.json('Invalid credentials');
} else {
const token = jwt.sign({
username: username
}, process.env.SECRET_KEY, {
expiresIn: 3600
});
return res.send({token});
}
});
module.exports = router;
i have a Problem with my project. I want to make a little download system for pictures, so i made a router for /download/:filename. I have the pictures in /userdata/${userId}/ and if i request /download/ with a param like test it logs in my console, but if i use a param wich exists in the userdata folder like Download.jpg it redirects me back to the homepath of the user: /file/${userId} here is my code:
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
const admin = require("./routes/admin");
import file from "./routes/file";
import download from "./routes/download";
const session = require("express-session");
var app = express();
app.set("trust proxy", 1);
app.use(session({
secret: "bla",
resave: false,
cookie: {
maxAge: 120000000
},
saveUninitialized: false
}));
function checkIfLoggedin(req,res,next){
if(!(req.originalUrl === "/") && !req.session.loggedIn){
res.redirect('/');
return;
}
next();
};
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(checkIfLoggedin);
app.use('/', index);
app.use("/admin", admin);
app.use("/file", file);
app.use("/download", download);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
index.js router
var express = require('express');
var router = express.Router();
const bcrypt = require('bcrypt-nodejs');
var dbPassword;
import mysql from "mysql";
//
/* GET home page. */
router.get('/', function(req, res, next) {
if (req.session.user != undefined) {
res.redirect("/file/"+req.session.user.userId);
}
else{
res.render('index', {});
}
});
router.post('/', function(req,res,next) {
console.log("1");
const enteredUsername = req.body.username;
const enteredPassword = req.body.password;
const con = mysql.createConnection({
host: "localhost",
user: "user",
password: "pass",
database: "db"
});
con.query('SELECT * FROM users WHERE username = ?;', [`${enteredUsername}`], (error, results, fields) => {
if (results.length > 0) {
console.log("2");
console.log(error);
let dbPassword = results[0].password;
bcrypt.compare(enteredPassword, dbPassword, (err,response) => {
console.log(err);
console.log(response);
console.log("3");
if (response == true) {
req.session.user = {
userId: results[0].userId,
username: results[0].username,
isAdmin: results[0].isAdmin,
};
req.session.loggedIn = true;
console.log("file");
if (req.session.user.isAdmin) {
res.redirect("/admin");
}
else{
res.redirect("/file/" + req.session.user.userId);
}
}
else{
req.session.loggedIn = false;
console.log("false");
res.send("Falsches Passwort");
}
});
}
else{
res.send("Falsche Daten");
}
});
});
router.get("/logout", (req,res,next) => {
if (req.session.user.userId) {
req.session.destroy();
res.redirect("/");
}
});
module.exports = router;
file.js
import express from "express";
import fs from "fs";
const router = express.Router();
const userDataPath = "/srv/www/www.precode.tech/www/userdata/";
router.get("/:userId", (req,res,next) => {
//console.log(req.params.userId == req.session.user.userId);
if (req.params.userId == req.session.user.userId) {
const userDataFiles = fs.readdirSync(userDataPath+req.session.user.userId);
res.render("file", {files : userDataFiles, user: req.session.user});
}
else{
res.status(403).render("unauthorized");
}
//res.send(`${req.params.userId} ${req.session.user.userId}`);
});
/*router.get("/:userId/download/:filename", (req,res,next) => {
console.log(req.params.filename);
if (req.params.userId == req.session.user.userId) {
let filePath = `${__dirname}/../userdata/${req.session.user.userId}/`;
res.download(filePath, req.params.filename);
next();
};
});*/
export default router;
download.js
import express from "express";
const router = express.Router();
/*router.get("/", (req,res,next) => {
res.send("download");
});*/
router.get("/:filename", (req,res,next) =>{
console.log(req.params.filename);
});
export default router;
It would be very nice, if you have ideas or see the problem.
Thank you :)
EDIT: It should not redirect to the base path of the user, the get request on download should allways console.log the item
I did not find the flaw, but let's cleanup the code and fix middleware attaching sequence (at least I saw cookie parser attached after session middleware, I suspect only that part) and check.
But let's check my code review / cleanup.
Really hope it helps.
app.js:
const express = require('express');
const path = require('path');
//const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const session = require("express-session");
const mysql = require('mysql');
const db = mysql.createConnection({
host: "localhost",
user: "user",
password: "pass",
database: "db"
});
const app = express();
app.set("trust proxy", 1);
// set view engine and renderer
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// serve static files
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); // no need for it since express static will serve all static files in public folder
app.use(express.static(path.join(__dirname, 'public')));
// connect morgan to profile requests
app.use(logger('dev'));
// parse cookies first
app.use(cookieParser());
// then handle session
app.use(session({
secret: "bla",
resave: false,
cookie: {
maxAge: 120000000
},
saveUninitialized: true
}));
// handle requests data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use((req, res, next) => {
req.db = db; // attach db connection to request context
next();
});
// public routes that does not need auth check
app.use('/', require('./routes/index'));
const checkIfLoggedin = (req, res, next) => {
if (!req.session.loggedIn) {
return res.redirect('/');
}
res.locals.user = req.session.user;
next();
};
// internal routes that needs auth check
app.use(
'/admin',
checkIfLoggedin,
require('./routes/admin'));
app.use(
'/files',
checkIfLoggedin,
require('./routes/files'));
/* no need for this route, it's covered in files.js
app.use(
'/download',
checkIfLoggedin,
download);
*/
// catch 404 and forward to error handler
app.use((error, req, res, next) => {
if (error) return next(error);
const err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use((error, req, res, next) => {
// set locals, only providing error in development
res
.status(error.status || 500)
.render('error', {
message: error.message,
error: req.app.get('env') === 'development' ? error : {}
});
});
module.exports = app;
routes/index.js:
const express = require('express');
const router = express.Router();
const logger = require('winston');
const bcrypt = require('bcrypt-nodejs');
const _ = require('lodash'); // install it: npm i --save lodash
/* GET home page. */
router.get('/', (req, res) => {
if (_.get(req, 'session.user.userId')) {
return res.redirect("/files/" + req.session.user.userId);
}
res.render('index', {});
});
router.post('/auth', (req, res, next) => {
const {username, password} = req.body;
const db = req.db;
const query = 'SELECT * FROM users WHERE username = ? LIMIT 1';
const fields = [username];
db.query(
query,
fields,
(err, result) => {
if (err) {
logger.error(err);
const error = new Error('System fehler');
return next(error);
}
const user = _.get(result, '0');
if (!user) {
req.session.loggedIn = false;
const error = new Error('Benutzer nicht gefunden');
error.status = 403;
return next(error);
}
bcrypt.compare(password, user.password,
(err, isEqual) => {
if(err || !isEqual) {
if (err) logger.error('Error in password compare:', err);
const error = new Error('Passwort ungültig');
error.status = 403;
return next(error);
}
req.session.user = _.pick(user, ['id', 'userId', 'username', 'isAdmin']);
req.session.loggedIn = true;
if (user.isAdmin) {
return res.redirect("/admin");
}
res.redirect("/files/" + user.userId);
});
});
});
router.get("/logout", (req, res) => {
// simply destroy session and redirect,
// no need for session check
req.session.destroy();
res.redirect("/");
});
module.exports = router;
routes/files.js:
const express = require('express');
const router = express.Router();
const logger = require('winston');
const fs = require('fs');
const path = require('path');
const async = require('async');
const userDataPath = path.join(__dirname, '..', 'userdata');
// no need to check userId with session.user.userId
// since middleware attached in app.js will guard this route
// and redirect user to '/'
router.get('/:userId', (req, res, next) => {
if(req.params.userId != req.session.user.userId) {
const error = new Error("You cannot access other user's files");
error.status = 403;
return next(error);
}
const directory = path.join(userDataPath, req.params.userId);
logger.info('Reading directory:', directory);
fs.readdir(
directory,
(err, entries) => {
if (err) {
logger.error(err);
const error = new Error('System error');
return next(error);
}
const directories = [];
const files = [];
async.eachLimit(
entries, 10,
(entry, done) => {
fs.stat(path.join(dir, entry), (error, stat) => {
if (stat.isFile()) files.push(entry);
if (stat.isDirectory()) directories.push(entry);
done();
});
},
() => {
res.render("files", {
directories,
files
});
});
});
});
router.get('/:userId/download/:filename', (req, res, next) => {
if(req.params.userId != req.session.user.userId) {
const error = new Error("You cannot access other user's files");
error.status = 403;
return next(error);
}
res.download(path.join(userDataPath, req.params.userId, req.params.filename));
});
module.exports = router;
P.S. If it works behind nginx, apache and etc make sure userdata folder is not accessible publicly.