I tried to make simple application with login and middleware.
const express = require('express');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('./services/CORS.service');
const authorization = require('./middleware/auth');
const loginRouter = require('./login/login.routes');
const usersRouter = require('./users/users.routes');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(cors);
app.use('/login', loginRouter);
app.use('/users', authorization, usersRouter);
const PORT = 5000;
app.listen(PORT, () => {
console.log(`Node app is running in: http://localhost:${PORT} ..`);
});
module.exports = app;
like you can see, I have login router and users with middleware router.
This is the loginRouter:
const express = require('express');
const router = express.Router();
const _ = require('lodash');
const cryptoService = require('../services/crypto/service');
router.post('/login', login);
async function login(req, res, next) {
try {
const { account, session } = await controller.login(req.body);
if (!req.body.username || !req.body.password) {
throw { message: 'Missing BasicAuth user and password', status: 400 };
}
const encryptedPassword = cryptoService.encrypt(password);
const toEncrypt = JSON.stringify({username: username, password: encryptedPassword, timestamp: new Date()});
const session = cryptoService.encrypt(toEncrypt);
res.status(200).send({ session });
}
catch (err) {
const errMessage = _.get(err, 'message', 'error occurred');
const errCode = _.get(err, 'status', 500);
res.status(errCode).json({ message: 'error occurred', error: errMessage });
}
}
module.exports = router;
and this is the middleware:
const _ = require('lodash');
const cryptoService = require('../services/crypto/service');
const moment = require('moment');
const SESSION_TOKEN_EXPIRATION_IN_MINUTES = 50;
module.exports = async function (req, res, next) {
try {
const session = _.get(req, 'headers.session');
console.log(session);
let decryptedSession = '';
try {
decryptedSession = cryptoService.decrypt(session);
}
catch (err) {
throw { message: 'Session is not valid, please re-login', status: 401 };
}
if (!decryptedSession) {
throw { message: 'No session provided, please re-login', status: 401 };
}
const { username, password, timestamp } = JSON.parse(decryptedSession);
if (!timestamp || moment.duration(moment().diff(timestamp)).asMinutes() > SESSION_TOKEN_EXPIRATION_IN_MINUTES) {
throw { message: 'Session expired, please re-login', status: 401 };
}
res.locals = res.locals || {};
res.locals.account = account;
next();
}
catch (err) {
const errMessage = _.get(err, 'message', 'error occurred');
const errCode = _.get(err, 'status', 500);
res.status(errCode).json({ message: 'error occurred during auth validation', error: errMessage });
}
};
when the application running, I sending postman post request to login with username and password in the body.
I got a correct session.
but when I open the users page I got error:
No session provided, please re-login
because the session in the middleware is undefined.
what can I do to fix this code?
tnx
Related
Using thunderclient (similar to postman) i cant access this employee api which requires a jwt, even though i confirm i am already authorized. Here is my code:
authController:
const usersDB = {
users: require("../model/users.json"),
setUsers: function (data) {
this.users = data;
},
};
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
require("dotenv").config();
const fsPromises = require("fs").promises;
const path = require("path");
const handleLogin = async (req, res) => {
const { user, pwd } = req.body;
if (!user || !pwd)
return res
.status(400)
.json({ message: "Username and password are required." });
const foundUser = usersDB.users.find((person) => person.username === user);
console.log(foundUser);
if (!foundUser) return res.sendStatus(401);
const match = await bcrypt.compare(pwd, foundUser.password);
if (match) {
const accessToken = jwt.sign(
{ username: foundUser.username },
process.env.ACCESS_TOKEN_SECRET,
{ expiresIn: "60s" }
);
const refreshToken = jwt.sign(
{ username: foundUser.username },
// we need our secret from env file as well to make our jwt
process.env.REFRESH_TOKEN_SECRET,
{ expiresIn: "1d" }
);
const otherUsers = usersDB.users.filter(
(person) => person.username !== foundUser.username
);
const currentUser = { ...foundUser, refreshToken };
usersDB.setUsers([...otherUsers, currentUser]);
await fsPromises.writeFile(
path.join(__dirname, "..", "model", "users.json"),
JSON.stringify(usersDB.users)
);
res.cookie("jwt", refreshToken, {
httpOnly: true,
ameSite: "None",
secure: true,
maxAge: 24 * 60 * 60 * 1000,
});
res.json({ accessToken });
} else {
res.sendStatus(401);
}
};
module.exports = { handleLogin };
sever.js:
const express = require("express");
const app = express();
const path = require("path");
const cors = require("cors");
const corsOptions = require("./config/corsOptions");
const { logger } = require("./middleware/logEvents");
const errorHandler = require("./middleware/errorHandler");
const cookieParser = require("cookie-parser");
const verifyJWT = require("./middleware/verifyJWT");
const PORT = process.env.PORT || 3500;
app.use(logger);
app.use(cors(corsOptions));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "./public")));
// routes
app.use("/", require("./routes/root"));
app.use("/register", require("./routes/register"));
app.use("/auth", require("./routes/auth"));
app.use("/refresh", require("./routes/refresh"));
app.use(verifyJWT);
app.use("/employees", require("./routes/api/employees"));
app.all("/*", (req, res) => {
res.status(404);
if (req.accepts("html")) {
res.sendFile(path.join(__dirname, "views", "404.html"));
} else if (req.accepts("json")) {
res.json({ error: "404 Not Found" });
} else {
res.type("txt").send("404 not found");
}
});
app.use(errorHandler);
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
verifyJWT middleware:
const jwt = require("jsonwebtoken");
require("dotenv").config();
const verifyJWT = (req, res, next) => {
const authHeader = req.headers["authorization"];
if (!authHeader) return res.sendStatus(401);
console.log(authHeader);
// bearer token, hence bearer space 1, 1 is the token
const token = authHeader.split("")[1];
// decoded info from the jwt
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, decoded) => {
// 403 is forbidden
if (err) return res.sendStatus(403);
req.user = decoded.username;
next();
});
};
module.exports = verifyJWT;
so if i for example
http://localhost:3500/auth (post) and login with a user and pwd, my res does log an access token, and if i try to use that inside
http://localhost:3500/employees (get) i get forbidden. not sure what i am missing here
i tried console.logging to see if i had foundUser, which i did, so not sure why i cant get into this route
You are splitting by empty string, it would divide every character, try spliting by space:
const token = authHeader.split(" ")[1];
I'm working on a node.js application.
In my application the requests are going through a middleware which checks if the user is authenticated. In my middleware file though, I keep getting the "next is not defined" error back in my client. What might be the issue? I'm adding the App.js and the middleware file in here:
App.js:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const graphqlHttp = require('express-graphql');
const { sequelize } = require('./models');
const graphqlSchema = require('./graphql/schema');
const graphqlResolver = require('./graphql/resolvers');
const auth = require('./middleware/auth');
// return instance of the app
app = express();
// setting up the cors config
app.use(cors({
origin: '*'
}));
// tell the app to parse the body of the request
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
// tell the app to go through the middleware before proceeding to graphql
app.use(auth);
// setting the graphql route
app.use('/graphql', graphqlHttp({
schema: graphqlSchema,
rootValue: graphqlResolver,
graphiql: true,
formatError(err) {
if (!err.originalError) {
return err;
}
const data = err.originalError.data;
const message = err.message || 'An error occurred.';
const code = err.originalError.code || 500;
return { message: message, status: code, data: data };
}
})
);
app.use((error, req, res, next) => {
const status = error.statusCode || 500;
const message = error.message;
const data = error.data;
res.status(status).json({ message: message, data: data });
});
sequelize.sync({ force: true })
.then(() => {
app.listen(8080);
})
.catch(err => {
console.log(err);
});
the auth.js file (the middleware):
const jwt = require('jsonwebtoken');
module.exports = (req, res, next) => {
const authHeader = req.get('Authorization');
if (!authHeader) {
req.isAuth = false;
return next();
}
const token = authHeader.split(' ')[1];
let decodedToken;
try {
decodedToken = jwt.verify(token, 'somesupersecretsecret');
} catch (err) {
req.isAuth = false;
return next();
}
if (!decodedToken) {
req.isAuth = false;
return next();
}
req.userId = decodedToken.userId;
req.isAuth = true;
next();
};
GET http://localhost:5000/booksIdea/show 403 (Forbidden)
i check the token in the website https://jwt.io/ i got invalid signature so i guess why the problem came from but i ignore how to fix it
i searched abt this error and this is what i found : Receiving a 403 response is the server telling you, “I’m sorry. I know who you are–I believe who you say you are–but you just don’t have permission to access this resource. Maybe if you ask the system administrator nicely, you’ll get permission. But please don’t bother me again until your predicament changes.”
API GET function on front end:
import axios from 'axios'
export const ShowBooks = () => {
let token = localStorage.getItem("usertoken")
return axios.get("http://localhost:5000/booksIdea/show", {
headers: {
Authorization: `Bearer ${token}`, //here remove + in template litereal
},
})
.then(res => {
console.log("Success")
})
.catch(error => {
console.log(error)
})
}
backend app.js
const express = require('express')
var cookieParser = require('cookie-parser')
const app = express()
var cors = require('cors')
var bodyParser = require('body-parser')
const port = 5000
const routes = require("./routes");
const con = require('./db')
var cors = require('cors')
app.use(cors())
// database connect
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
//cookie
app.use(cookieParser())
//routes
// support parsing of application/json type post data
app.use(bodyParser.json());
//support parsing of application/x-www-form-urlencoded post data
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/", routes);
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
here is routes
var express = require('express')
var router = express.Router()
var Controller = require('./controller')
var authController = require('./authController')
var BooksIdeaController = require('./BooksIdeaController')
router.post('/register',Controller.register);
router.post('/login',authController.login);
router.post('/booksIdea/:id',authController.verify,BooksIdeaController.addComment)
router.post('/booksIdea/addbook',authController.verify,BooksIdeaController.addBookIdea)
router.get('/booksIdea/show',authController.verify,BooksIdeaController.showBookIdea)
router.put('/booksIdea/edit/:id',authController.verify,BooksIdeaController.UpdateBookIdea)
router.delete('/booksIdea/delete/:id',authController.verify,BooksIdeaController.DeleteBookIdea)
module.exports = router;
authController
const con = require('./db');
var bcrypt = require('bcrypt');
let jwt = require('jsonwebtoken');
const express = require('express')
var cookieParser = require('cookie-parser')
const app = express()
module.exports.login=function(req,res){
var username=req.body.name;
var password=req.body.password;
con.query('SELECT * FROM users WHERE username = ?',[username], function (error, results, fields) {
if (error) {
res.json({
status:false,
message:'there are some error with query'
})
}else{
if(results.length >0){
bcrypt.compare(password, results[0].password, function (err, result) {
if (result == true) {
jwt.sign({user:results},'configSecret',(err,token)=>{
res.json({
token:token
})
});
// res.json({
// status:true,
// message:'successfully authenticated'
// })
} else {
res.json({
status:false,
message:"username and password does not match"
});
}
});
}
else{
res.json({
status:false,
message:"username does not exits"
});
}
}
});
}
module.exports.home=function(req,res){
res.send('hello');
}
//////
// if(password==results[0].password){
// }else{
//
// }
module.exports.verify = function verifyToken(req, res, next) {
// Get auth header value
const bearerHeader = req.headers['authorization'];
// Check if bearer is undefined
if(typeof bearerHeader !== 'undefined') {
// Split at the space
const bearer = bearerHeader.split(' ');
// Get token from array
const bearerToken = bearer[1];
// Set the token
req.token = bearerToken;
// Next middleware
next();
} else {
// Forbidden
res.sendStatus(403);
}
}
How can I fix this error? thank you in advance for your help
Check your localstorage localStorage.getItem("usertoken")
Your token can be:
missing or undefined
incorrect token - probably a typo
Been trying to get user user object by id from parameters, using User.findById and cannot access this route.
Postman response: Cannot GET /users/get/ with status 404 (not found) which is wierd.
Postman JSON response:
Unexpected '<'
Been using express-promise-router but also tried with default express.Router();
Here is my code:
routes/users.js
const express = require('express');
const router = require('express-promise-router')();
const passport = require('passport');
const router1 = express.Router();
require('../passport');
const { validateBody, schemas } = require('../helpers/routeHelpers');
const UsersController = require('../controllers/users');
const passportSignIn = passport.authenticate('local', { session: false });
const passportJWT = passport.authenticate('jwt', { session: false });
router.route('/signup')
.post(validateBody(schemas.authSchema), UsersController.signUp);
router.route('/signin')
.post(validateBody(schemas.authSchema), passportSignIn, UsersController.signIn);
router.route('/get/:id')
.get(UsersController.getUser);
router.route('/secret')
.get(passportJWT, UsersController.secret);
controllers/users
module.exports = router;
const JWT = require('jsonwebtoken');
const User = require('../models/user');
const { JWT_SECRET } = require('../configuration');
const signToken = (user) => {
return JWT.sign({
iss: 'CodeWorkr',
sub: user.id,
iat: new Date().getTime(), // current time
exp: new Date().setDate(new Date().getDate() + 1) // current time + 1 day ahead
}, JWT_SECRET);
};
module.exports = {
signUp: async (req, res) => {
const { email, password } = req.value.body;
// Check if there is a user with the same email
const foundUser = await User.findOne({ 'local.email': email });
if (foundUser) {
return res.status(403).json({ error: 'Email is already in use' });
}
// Create a new user
const newUser = new User({
method: 'local',
local: {
email: email,
password: password
}
});
await newUser.save();
// Generate the token
const token = signToken(newUser);
// Respond with token
return res.status(200).json({ token });
},
signIn: async (req, res) => {
// Generate token
const token = signToken(req.user);
res.status(200).json({ token });
},
getUser: async (req, res) => {
User.findById(req.params.id)
.then((user) => {
res.status(200).json({ user });
console.log('test');
});
},
secret: async (req, res) => {
console.log('I managed to get here!');
res.json({ secret: 'resource' });
}
};
server.js
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const passport = require('passport');
const db = require('./configuration/config').mongoURI;
const dbTest = require('./configuration/config').mongoURITest;
mongoose.Promise = global.Promise;
if (process.env.NODE_ENV === 'test') {
mongoose.connect(dbTest, { useMongoClient: true });
} else {
mongoose.connect(db, { useMongoClient: true });
}
const app = express();
app.use(cors());
app.use(passport.initialize());
app.use(passport.session());
// Middlewares moved morgan into if for clear tests
if (!process.env.NODE_ENV === 'test') {
app.use(morgan('dev'));
}
app.use(bodyParser.json());
// Routes
app.use('/users', require('./routes/users'));
// Start the server
const port = process.env.PORT || 3001;
app.listen(port);
console.log(`Server listening at ${port}`);
Other post routes works fine,
I have tried to post in MongoDB by using postman while posting a text i got a error of (Couldnt get any Response) It is not showing any error to Command nodemon Please help me where i did mistake ..! what i need to do ?
My index.js file is:-
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const config = require('./configdb/database');
// Connection to database
mongoose.connect(config.database);
// Connection Success to DB
mongoose.connection.on('connected',() => {
console.log('Connected to the Database ' +config.database);
});
//on Error while Connecting
mongoose.connection.on('error',(err) => {
console.log('connection ERROR Try Again Database Failed to Connect ' +err);
});
const app = express();
const articles = require('./routers/articles');
// Port to start
const port = 2200;
// cors middleware
app.use(cors());
// Set Static Public folder
app.use(express.static(path.join(__dirname, 'public')));
// Body Parser Middleware
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json());
app.use('/articles',articles);
// Index Route
app.get('/', (req, res) => {
res.send('this is initial page for starting all session')
});
app.listen(port, () => {
console.log('server started in' + port)
})
my articles.js file is
const express = require('express');
const router = express.Router();
const config = require('../configdb/database');
const Article = require('../models/article');
// Register of article
router.post('/new-article', (req,res,next) => {
let article = new Article();
article.title = req.body.title;
console.log(req.body.title);
return;
article.save(function(err){
if(err){
res.json({success: false, msg: 'Failed to Register the Article' });
} else {
res.json({success: true, msg: 'New Article is Registered'});
}
});
});
module.exports = router;
my article.js file is
const mongoose = require('mongoose');
const config = require('../configdb/database');
const ArticleSchema = mongoose.Schema({
title:{
type: String,
}
});
const Article = module.exports = mongoose.model('Article', ArticleSchema)
But I have got the message from
article.title = req.body.title; and my error as follows:-
In articles.js you have return the function after displaying title cause the problem!
// Register of article
router.post('/new-article', (req, res, next) => {
let article = new Article();
article.title = req.body.title;
console.log(req.body.title);
// return;
article.save(function (err) {
if (err) {
res.json({
success: false,
msg: 'Failed to Register the Article'
});
} else {
res.json({
success: true,
msg: 'New Article is Registered'
});
}
});
});