I'm currently facing the following error, I'm developing an API in node js for let's say a virtual shop. An user, for getting its items in cart needs to be authenticated. The authentication is being handled via JWT, and im using passport module for that propose.
For the routes that require authentication, when the API is consumed using the 'Authentication' header with its correspondent 'JWT ey...' token, the server is not handling any request. Just responds to the OPTIONS preflight request and nothing more. I've tried consuming the /api/cart from an angular front end using httpClient, and the authorization header and getting the following error in the chrome devTools
As well i've tried using postman, sending the authorization header and couldn't get any response screen appears.
I'm logging the OPTIONS request headers. The following is the server response after hitting /api/cart with authorization header and it stops there.
!OPTIONS
{ host: 'localhost:3000',
connection: 'keep-alive',
'access-control-request-method': 'GET',
origin: 'http://localhost:4200',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36',
'access-control-request-headers': 'authorization,content-type',
accept: '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9' }
!OPTIONS
OPTIONS /api/cart 200 1.288 ms - -
server.js
const mongoose = require("mongoose");
const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const passport = require("passport");
const config = require("./config/database"); //Getting databas config file
const User = require("./app/models/user"); //we're getting mongoose model
const Product = require("./app/models/product");
const app = express();
const port = process.env.PORT || 3000;
const routes = require("./app/routes/index");
mongoose.connect(config.database);
//bodyParser to get our request/response parameters
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json({ limit: "50mb" }));
//log request to console
app.use(morgan("dev"));
app.use(passport.initialize());
//pass passport for connfiguration
require("./config/passport")(passport);
//allow cors
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
);
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, OPTIONS, PUT, PATCH, DELETE"
);
if (req.method === "OPTIONS") {
console.log("!OPTIONS");
res.end();
}
next();
});
routes(app);
app.listen(port);
console.log("express app started on port " + port);
routes/index.js
const productApiRouter = require("./product.routes");
const userApiRouter = require("./user.routes");
module.exports = (app) => {
app.use("/api", userApiRouter); //routes for users
app.use("/products", productApiRouter); // routes for products
};
routes/user.routes
require('../models/user')
const express = require('express');
const passport = require('passport')
const isAuthenticated = require('../controllers/auth.controller')
const router = express.Router();
var userController = require('../controllers/user.controller');
router.get('/', userController.getUser)
router.get('/cart', passport.authenticate('jwt', {
session: false,
failWithError: true
}), userController.getCart)
router.post('/deletecart/:id', userController.deleteCartById)
router.post('/authenticate', userController.authenticate)
router.post('/signup', userController.signupUser)
router.get('/verify_email', userController.verifyEmailByUrl)
router.post('/addcart/:id', userController.addItemToCart)
router.post('/update_user', userController.updateUser)
module.exports = router;
controllers/user.controller.js get cart method
exports.getCart = (req, res) => {
var token = getToken(req.headers);
if (token) {
var decoded = jwt.decode(token, config.secret);
User.findOne(
{
email: decoded.email
},
function(err, user) {
if (err) throw err;
if (!user) {
return res.status(404).send({
success: false,
message: "Not user found"
});
} else {
var cart = user.itemsInCart;
console.log(cart);
var items = addItemCount.addItemCount(cart);
console.log(items);
res.status(200).send(JSON.stringify(items));
}
}
);
} else {
console.log('Request ')
res.status(403).send({
success: false,
message: "Unauthorized request"
});
}
};
config/passport ---> passport configuration
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const User = require('../app/models/user');
const config = require('./database');
//add a JWT strategy to our passport
module.exports = function(passport) {
var opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme("jwt");
opts.secretOrKey = config.secret;
passport.use('jwt', new JwtStrategy(opts, function(jwt_payload, done) {
User.findOne({
id: jwt_payload.id //try to find a user given jwt_payload.id
}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false)
}
});
}));
}
getToken function
var getToken = function(headers) {
if (headers && headers.authorization) {
var parted = headers.authorization.split(' ');
if (parted.length === 2) {
return parted[1];
} else {
return null;
}
} else {
return null;
}
};
module.exports = getToken
jwt
declared? It is used asjwt.decode(token, config.secret);
. Also, can you post code ofgetToken
? – Vasannext
nor finishing response. – Vasan