401: unauthorized (it contains bearer token) - authorization

Login module is working and creating users with token 201 created
Receipts route had worked with the same code before but now response is 401
using Postman (Authorization & Bearer: xcvbnm) has been put
Here is my code
server.js
const express = require('express')
require('./db/mongoose')
const userRouter = require('./routes/user')
const receiptRouter = require('./routes/receipt')
const app = express()
const port = process.env.PORT || 4003
app.use(express.json())
app.use(userRouter)
app.use(receiptRouter)
app.listen(port, () => {
console.log('Server is up on port ' + port)
})
const Receipt = require('./models/receipt')
const User = require('./models/user')
Receipts Route
router.post('/receipts', auth, async (req, res) => {
const receipt = new Receipt({
...req.body,
owner: req.user._id
})
try {
await receipt.save()
res.status(201).send(receipt)
} catch (e) {
res.status(400).send(e)
}
})
Receipt Schema
const Receipt = mongoose.model('Receipt', {
description: {
type: String,
required: true,
trim: true
},
})
Auth module
const auth = async (req, res, next) => {
try {
const token = req.header('Authorization').replace('Bearer', '')
const decoded = jwt.verify(token, 'Mango#123')
const user = await User.findOne({ _id: decoded._id, 'tokens.token': token })
if (!user) {
throw new Error()
}
req.token = token
req.user = user
next()
} catch (e) {
res.status(401).send({ error: 'Please authenticate.' })
}
}

Related

how to delete cookie without reloading the page using custom express server in next js

this is my routes file
const User = require("./schema");
const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");
const express = require("express");
const server2 = express();
const routes = (server,app) => {
// this route is for signup
server.post("/api/signup", async (req,res) => {
const { fullName, emailId, password }=req.body;
const signupData = new User({
fullName,
emailId,
password: await bcrypt.hash(password,10),
});
const token = await signupData.generateToken();
console.log(`token: ${token}`);
if (token != undefined) {
res.cookie("token",token,{
httpOnly: true,
secure: true,
sameSite: "strict",
path: "/",
maxAge: 1000*60*2
})
res.send({message:"signedup successfuly"});
res.end();
}
const saveUser = await signupData.save();
});
// this route is for user varification
server.get("/api", async (req,res) => {
const token = req.cookies.token;
console.log(`token: ${token}`);
if (token != undefined) {
const _id = jwt.verify(token,process.env.JWT_SECRET)._id;
const findUser = await User.findOne({ _id });
res.send(findUser);
} else {
res.send({fullName:""});
}
});
// this route is for logout
server.get("/api/logout",async (req, res) => {
try {
const token = req.cookies.token;
const _id = jwt.verify(token, process.env.JWT_SECRET)._id;
await User.updateOne({ _id }, { $pull: { tokens: { token }}});
res.clearCookie("token");
console.log(req.cookies.token)
res.send({message:""})
res.end();
} catch(err) {
console.log(err)
}
});
}
module.exports = routes;
When I do signup cookie is setting without reloading the page its working but that's not a problem the problem is when I do logout its not deleting cookie without reloading the page when I reload the page its working but without reloading the page its not working I am using custom express server in nextjs

Router export failing while exporting multiple functions (TypeError: app.use() requires a middleware function)

I'm having this odd error and I'm not knowing what to do to make it work. The thing is, I need to export some functions and express router. The thing is, if I try to set
module.exports = {router, function1, function2}
it gaves me that error
(TypeError: app.use() requires a middleware function).
If I try to set my functions with exports.function1 = async function function1 (req,res) {blablabla} they get exported but I still get the same error... I need to use the functions in this way
router.get('/api/auth0/users', async (req, res,next) => {
function1(res, next)
})
and I'm lacking ideas... and have no clue of why the multiple module.exports it's not working since I've used it a lot (seems like the problem is with the router.... (NOTE: I've just used an example code since mine is a 140 lines src)
(NOTE2: function1 and function2 are async since they make queries to MongoDB)
UPDATE: (Adding the import codes)
I import it in my main .js file like this
const {router} = require('./auth/auth0')
then tell app to use it like this
app.use(router);
app is defined using this lines
const express = require("express");
const app = express();
changing the export/import name to another like authRouter or something makes no difference.
Heres the complete code:
const router = require('express').Router()
const express = require('express')
const passport = require('passport');
const session = require('express-session')
const {generateJwt} = require("../helpers/generateJwt");
const usuarios = require('../models/usuarios')
let OpenIDConnectStrategy = require('passport-openidconnect');
passport.serializeUser(function (user, cb) {
cb(null, user);
});
passport.deserializeUser(function (obj, cb) {
cb(null, obj);
});
passport.use(new OpenIDConnectStrategy({
issuer: 'https://' + process.env.AUTH0_DOMAIN + '/',
authorizationURL: 'https://' + process.env.AUTH0_DOMAIN + '/authorize',
tokenURL: 'https://' + process.env.AUTH0_DOMAIN + '/oauth/token',
userInfoURL: 'https://' + process.env.AUTH0_DOMAIN + '/userinfo',
clientID: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
callbackURL: '/login/callback',
scope: [ 'profile', 'email' ]
},
function verify(issuer, profile, cb) {
if(profile){
userEmail = profile.emails[0].value
userProfile = profile
whoIs = profile.id
}
return cb(null,profile)
}
));
router.use(express.json())
router.use(session({ secret: 'keyboard cat~troubles', secured:true, key: 'sid', saveUninitialized: true, resave: false}));
router.use(passport.initialize())
router.use(passport.session())
var userProfile = ""
let userEmail = ""
let whoIs = ""
let token = ""
async function createUser(res,next) {
try {
token = await generateJwt(whoIs, process.env.JWT_SECRET_KEY);
const nAccount = new usuarios({
nombre: userProfile.name.givenName,
apellido: userProfile.name.familyName,
auth0Id: whoIs,
email: userEmail,
token: token
});
await nAccount.save()
return res.status(201).json({Status: "Cuenta creada exitosamente", token: token});
} catch (error) {
console.log(error)
return res.redirect('/api/auth0/logged')
}
}
async function findUser(res, next){
try{
let email = userEmail
let mailEncontrado = await usuarios.findOne( {email} )
if (!mailEncontrado ){
return res.redirect('/api/auth0/register')
}
else {
token = await generateJwt(whoIs, process.env.JWT_SECRET_KEY);
let userID = await usuarios.findOneAndUpdate(
{email},
{ nombreAuth0: userProfile.name.givenName,
apellidoAuth0: userProfile.name.familyName,
auth0Id: whoIs,
token: token},
{ new: true }
)
return res.redirect('/api/auth0/logged')
}
}
catch (err) {
console.log(err)
}
}
async function userAuthenticated(res, next) {
if( req.isAuthenticated() === true){
console.log(req.isAuthenticated())
return true
} else{
console.log(req.isAuthenticated())
return false
}
}
router.get('/api/auth0/login', passport.authenticate('openidconnect',{prompt: 'login', failureMessage: true}));
router.get('/api/auth0/users', async (req, res,next) => {
findUser(res, next)
})
router.get('/api/auth0/register', async (req, res,next) => {
createUser(res, next)
})
router.get('/login/callback', passport.authenticate('openidconnect', {
successRedirect: '/api/auth0/users',
failureRedirect: '/api/auth0/login'
}));
router.get('/api/auth0/logged', (req, res) => {
if(whoIs === ""){
return res.status(401).json('Error de autenticacion')
}
else {
console.log(whoIs)
return res.status(201).json({Status: 'Usuario logueado. ID = '+ whoIs, Token: token, Email: userEmail})
}
})
router.get('/api/auth0/logout', (req, res) => {
if(!req.user){
res.json("No hay usuario autenticado")
}
req.logout()
res.status(201).json("Sesion finalizada exitosamente.")
})
module.exports = {router, userAuthenticated}

timeout async callback testing with sinon jest supertest to simulate error 500 on express api

I am testing an api with all http 500 errors.
Here I try to use sinon.stub to test on a failing server and get a 500 error, but I get a timeOut async callback, or if I use my app a successfull 200 response statusCode as if sinon.stub has no effect. I must miss something and I am stucked...
would you see a horrifying error below ?
thanks for your precious help
process.env.NODE_ENV = "test";
const app = require("../../app");
const request = require("supertest");
const sinon = require("sinon");
// /************************** */
const usersRoute = require("../../routes/Users");
const express = require("express");
const initUsers = () => {
const app = express();
app.use(usersRoute);
return app;
};
describe("all 5xx errors tested with stub", function () {
it("should return a 500 when an error is encountered", async (done) => {
let secondApp;
sinon.stub(usersRoute, "post").throws(
new Error({
response: { status: 500, data: { message: "failed" } },
})
);
secondApp = initUsers(); //==========> Timeout Async Callback
//secondApp = require("../../app"); //==============> gives a 200 instead of 500
const fiveHundredError = await request(secondApp)
.post("/users/oauth?grant_type=client_credentials")
.send({
username: "digitalAccount",
password: "clientSecret",
});
expect(fiveHundredError.statusCode).toBe(500);
//sinon.restore();
done();
});
});
app is using express.Router to get users route :
const express = require("express");
const router = express.Router();
const axios = require("axios");
router.post("/users/oauth", async (req, res) => {
//if (all missing parts)
//else {
try {
if (req.fields) {
const response = await axios.post(
`${base_url}oauth/token?grant_type=${req.query.grant_type}`,
{},
{
auth: {
username: req.fields.username,
password: req.fields.password,
},
}
);
res.json(response.data);
}
} catch (error) {
return res.status(error.response.status).json(error.response.data);
}
}
});
module.exports = router;
See server.js :
const app = require("./app");
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`server starting on port ${port}!`));
and app.js :
// private environment:
require("dotenv").config();
const express = require("express");
const formidableMiddleware = require("express-formidable");
const cors = require("cors");
const app = express();
app.use(formidableMiddleware());
app.use(cors());
const usersRoute = require("./routes/Users");
app.use(usersRoute);
app.get("/", (req, res) => {
res.status(200).send("Welcome to Spark Admin back end!");
});
app.all("*", (req, res) => {
return res.status(404).json({ error: "Web url not found" });
});
module.exports = app;
I finally opted for 'nock' and deleted 'sinon'
const nock = require("nock");
const axios = require("axios");
describe("POST login: all 5xx errors tested with nock", function () {
it("should return a 500 when an error is encountered", async (done) => {
const scope = nock("http://localhost:5000")
.post(
"/users/oauth",
{},
{
username: "blibli",
password: "blabla",
}
)
.reply(500, {
response: {
statusCode: 500,
body: { error: "AN ERROR OCCURED" },
},
});
try {
await axios.post(
"http://localhost:5000/users/oauth",
{},
{
username: "blibli",
password: "blabla",
}
);
} catch (e) {
expect(e.response.status).toBe(500);
}
done();
});
});

How to use async and await with Express and MongoDB

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongodb = require('mongodb');
const app = express();
app.use(cors())
app.use(bodyParser.json());
const MongoClient = mongodb.MongoClient;
const url = "mongodb://localhost:27017/recart";
app.post("/register" , (req, res) => {
const { displayName, email, password } = req.body;
if (!email || !displayName || !password) {
return {code: 400, msg: "incorrect form submission"}
}
let insertedid = null
MongoClient.connect(url, (err, db) => {
if (err) throw err;
var dbo = db.db("recart");
var myobj = { displayName: displayName, email: email, password: password };
dbo.collection("customers").insertOne(myobj)
.then(res => {
insertedid = res.insertedId
})
});
res.json({id: insertedid})
})
app.listen(process.env.PORT || 3000, ()=> {
console.log(`App is running on port 3000`);
})
Here, I am storing data inside db and sending the last inserted id
to the frontend.
However, id is returning null.
How can I use async and await to solve this issue?
You can modify your post function using async await like this:
app.post("/register", async (req, res) => {
const { displayName, email, password } = req.body;
if (!email || !displayName || !password) {
return {code: 400, msg: "incorrect form submission"}
}
let insertedid = null ;
MongoClient.connect(url,{ useNewUrlParser: true }, async (err, db) => {
if (err) throw err;
var dbo = db.db("recart");
var myobj = { displayName: displayName, email: email, password: password };
var result = await dbo.collection("customers").insertOne(myobj);
insertedid = result.insertedId;
res.json({ id: insertedid})
});
})

How can I pass paramters in a middleware call to the middleware?

So I am trying to pass a parameter in my middleware call in my router and then catch that data in the middleware.
I keep getting the following error: Error: Route.post() requires a callback function but got a [object Promise]
// admin router
const express = require('express')
const Admin = require('../models/users/admin')
const auth_admin = require('../middleware/auth_admin')
const router = new express.Router()
const mongoose = require('mongoose')
router.post('/', auth_admin('text'), async (req, res) => {
// code placeholder
})
module.exports = router
// middleware
const jwt = require('jsonwebtoken')
const Admin = require('../models/users/admin')
module.exports = function auth_admin(data) {
return function async (req, res, next) {
console.log(data)
try {
const token = req.header('Authorization').replace('Bearer ', '')
const decoded = jwt.verify(token, 'f33~#%d6gf63geswg###F3f')
const admin = await Admin.findOne({ _id: decoded._id, 'tokens.token': token })
if (!admin) {
throw new Error()
}
req.token = token
req.admin = admin
next()
} catch(err) {
res.status(401).send({error: 'Authentication failed.'})
}
}
}
instead for passing additional parameter add property to req object, and then access this property in the middleware function.
eg:
// admin router
const express = require('express')
const Admin = require('../models/users/admin')
const auth_admin = require('../middleware/auth_admin')
const router = new express.Router()
const mongoose = require('mongoose')
router.post('/', async function async(req, res, next) {
req.middlewareData = 'text';
next()
}, auth_admin, async (req, res) => {
// code placeholder
})
module.exports = router
// middleware auth_admin
const jwt = require('jsonwebtoken')
const Admin = require('../models/users/admin')
exports.auth_admin = function async(req, res, next) {
console.log(req.middlewareData)
try {
const token = req.header('Authorization').replace('Bearer ', '')
const decoded = jwt.verify(token, 'f33~#%d6gf63geswg###F3f')
const admin = await Admin.findOne({ _id: decoded._id, 'tokens.token': token })
if (!admin) {
throw new Error()
}
req.token = token
req.admin = admin
next()
} catch (err) {
res.status(401).send({ error: 'Authentication failed.' })
}
}