Cognito authenticating entire EC2 instance... or so it it seems? - node.js

It appears as though when I sign into my application, it is storing the credentials locally on the EC2 server. I've quadruple checked my code and I can't figure out what the deal is. If KEVIN signs in from any device, the next user to sign in, or if someone refreshes their page they end up signed in as KEVIN. I am including all code that could potentially be involved in the issue. Outside of this problem, all of my interaction with cognito works great; no errors & no problems. Any help would be greatly appreciated. I am using Node.js, Express, AWS, and Websockets on my EC2 Instance.
// Accessed from server for route authentication before page render or redirection
const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
module.exports = {
ensureAuthenticated: function(req, res, next) {
let data = { UserPoolId : 'us-east-1_7xUGRJPKq',
ClientId : '6glign6b34c806osfhnik18cb3'
};
let userPool = new AmazonCognitoIdentity.CognitoUserPool(data);
let cognitoUser = userPool.getCurrentUser();
console.log(`ensuring authentication....`);
console.log(cognitoUser);
if (cognitoUser === null) {
req.flash('error_msg', 'Please log in');
res.redirect('/login');
} else {
cognitoUser.getSession((err, session) => {
if (err) {
console.log(err);
} else {
next();
}
});
}
},
};
// Routes where I am seeing the problem
const express = require('express');
const router = express.Router();
const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
const { ensureAuthenticated } = require('../config/auth.js');
router.get('/', (req, res) => {
res.redirect('/dashboard');
});
router.get('/dashboard', ensureAuthenticated, (req, res) => {
res.render('dashboard', {
layout: './layouts/dashboard-layout.ejs'
});
});
// Login authentication
router.post('/login', (req, res) => {
const loginDetails = {
Username: req.body.email,
Password: req.body.password
}
const authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(loginDetails);
const userDetails = {
Username: req.body.email,
Pool: userPool
}
const cognitoUser = new AmazonCognitoIdentity.CognitoUser(userDetails);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: data => {
cognitoUser.getUserAttributes(function(err, result) {
if (err) {
console.log(err);
return;
} else {
console.log('LOGIN RESULTS')
console.log(result[0].Value.toString());
let userId = result[0].Value.toString();
let userCity = result[2].Value.toString();
console.log(userId);
console.log(userCity);
res.redirect(`/dashboard/${userCity}/${userId}/`)
};
});
},
onFailure: err => {
req.flash('error_msg', 'Invalid Credentials');
console.error(err);
res.redirect('/login');
}
})
});
Thank You!
UPDATE 10/21/19: Removed function that doesn't apply to the issue.
Also do not seem to have any JWT in local storage:
Click Here for image

Related

How to update the current session when updating an array with mongoose push. Using express handlebars mongoose and node.js

I am currently trying to create a social media app, where you can only see posts of your friends and direct message only with friends. Unfortunately when adding a friend by updating the database with mongoose by pushing an item into a friends array (which works perfectly). when i then visit posts or messages, the friends has not been updated and requires logging out and then logging in again, which updates it to work exactly how I envisioned. Is this something to do with the way that the friends array is being updated?
The friends update array:
const User = require("../models/user");
const FriendsController = {
Update: (req, res) => {
const requesterUserID = req.session.user._id
const receiverUserID = req.params.userID
User.findOne({ _id: receiverUserID }).then((user) => {
user.friends.push(requesterUserID);
user.save(() => {
User.findOne({ _id: requesterUserID}).then(user2 => {
user2.friends.push(receiverUserID)
user2.save(() => {
res.redirect(`/profile/${receiverUserID}`);
});
})
});
});
}
};
module.exports = FriendsController;
I cannot for the life of me figure out what is going on. I am assuming it is related to the session given the fact that it works upon refreshing the session by logging out and logging in again.
The session controller:
const User = require("../models/user");
const bcrypt = require("bcryptjs");
const SessionsController = {
New: (req, res) => {
res.render("sessions/new", {});
},
Create: (req, res) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email: email }).then((user) => {
if (user) {
bcrypt.compare(password, user.password).then((result) => {
if (result) {
req.session.user = user;
res.redirect("/posts");
} else {
res.render("sessions/new", { signInError: true });
}
});
} else {
res.render("sessions/new", { signInError: true });
}
});
},
Destroy: (req, res) => {
console.log("logging out");
if (req.session.user && req.cookies.user_sid) {
res.clearCookie("user_sid");
}
res.redirect("/sessions/new");
},
};
module.exports = SessionsController;
clearing cookie upon logging out:
app.use((req, res, next) => {
if (req.cookies.user_sid && !req.session.user) {
res.clearCookie("user_sid");
}
next();
});
Thanks in advance for the help

Passport authenticate jwt not responding

I have a basic MERN login/signup app with a dummy protected route to be visible only to logged in users. I have set up everything related to login and sign up.
I am sending the jwt token from server in a cookie. The aprt up to this works fine. I can sign up and I can login.
But when I make a GET call to /protected route, passport.jwt doesn't seem to work. Nothing happens in there.
Here is my passport.js config:
import {Strategy} from 'passport-jwt';
// import {ExtractJwt} from 'passport-jwt';
import passport from 'passport';
import mongoose from 'mongoose';
import {UserSchema} from '../models/userModel';
import {config} from './config';
const User = mongoose.model('User', UserSchema);
const cookieExtractor = (req) => {
let token = null;
if(req && req.cookies) {
token = req.cookies['jwt'];
}
return token;
}
export const passportConfig = (passport) => {
const opts = {};
opts.jwtFromRequest = cookieExtractor;
opts.secretOrKey = config.key;
passport.use(
new Strategy(opts, (jwt_payload, done) => {
User.findById(jwt_payload.id)
.then((user) => {
if(user) {
return done(null, user);
}
return done(null, false);
})
.catch((err) => {
console.log('Error in finding user by id in jwt.');
});
})
);
};
Here is the userRoutes.js:
import { addNewUser, loginUser, verifyLogin } from '../controllers/userController';
export const routes = (app) => {
app.route('/users/register')
.post(addNewUser);
app.route('/users/login')
.post(loginUser);
app.route('/users/protected')
.get(verifyLogin);
}
Finally, here are the verifyLogin and loginUser controllers in my userController.js:
export const loginUser = (req, res) => {
console.log(req.body);
if(mongoSanitize.has(req.body)) {
return res.send(400).json({error: "Characters $ and . are prohibited. Use different values."});
}
const {errors, isValid} = validateLoginInput(req.body);
if(!isValid) {
return res.status(400).json(errors);
}
const userName = req.body.userName;
const password = req.body.password;
User.findOne({userName: userName})
.then((user) => {
if(!user) {
return res.status(404).json({userNotFound: "Username not found."});
}
else {
bcrypt.compare(password, user.password)
.then((isMatch) => {
if(isMatch) {
const payload = {
id: user.id,
name: user.fullName
};
const token = jwt.sign(payload, config.key, {expiresIn: 60});
res.cookie('jwt', token, {httpOnly: true, secure: false});
res.status(200).json({success: true, token: token});
}
else {
return res.status(400).json({incorrectPassword: "Password incorrect."});
}
})
}
});
};
export const verifyLogin = () => {
console.log('protected'); //'protected' is printed
passport.authenticate('jwt', {session: false}),
(req, res) => {
console.log('here'); //'here' is not printed
const { user } = req;
res.send(200).send({user});
};
};
The controller loginUser works just fine, I can see the token in response and also I have a cookie with the jwt key:value pair.
But the 3rd controller verifyLogin doesn't do anything after passport.authenticate call.
Any ideas where I might be doing something wrong ?
Okay so I was able to fix. Anyone else having the same problem, the issue was that I wasn't using passport.authenticate as a middleware, instead I was calling it as a function with a callback on successful authentication. Here are the change that I made:
userRoutes.js:
export const routes = (app) => {
app.route('/register')
.post(addNewUser);
app.route('/login')
.post(loginUser);
app.route('/protected')
.get(passport.authenticate('jwt', {session:false}), verifyLogin);
}
And then verifyLogin just sends the logged in user information back:
export const verifyLogin = (req, res) => {
console.log('here');
const { user } = req;
res.status(200).json({message:'Secure route', user: user});
};
Everything else is pretty much the same.
I had the same problem until I changed the time to 1 hour. It seems like the value you wrote is in milliseconds, so instead of 60 you should write 60000.

How to test authentication with jwt inside a cookie with supertest, passport, and JEST

Hey guys I am currently am trying to do something similar to what is posted here:
How to authenticate Supertest requests with Passport?
as I would like to test other endpoints that require authentication but in addition need to pass in a jwt. Right now, I tested it on POSTMAN and on the browser and it seems like it's working fine, but my test cases keep on breaking. I have a login POST route that is setup like so:
AccountService.js
// Login POST route
router.post('/account_service/login', (req, res, next) => {
passport.authenticate('local-login', (err, user, info) => {
try {
if (err) {
const error = new Error('An Error occurred: Cannot find user');
return next(error);
} else if (!user) {
return res.redirect('/account_service/login');
}
req.login(user, { session: false }, (error) => {
if (error) {
return next(error);
}
const email = req.body.email;
const role = req.user[0].role;
const id = req.user[0].id;
const user = {
email: email,
role: role,
id: id
};
const accessToken = jwt.sign(user, config.ACCESS_TOKEN_SECRET, {
expiresIn: 28800 // expires in 8 hours
});
const cookie = req.cookies.cookieName;
if (cookie === undefined) {
// set a new cookie
console.log('setting new cookie');
res.cookie('jwt', accessToken, { maxAge: 900000, httpOnly: true });
res.send({ token: accessToken });
} else {
// cookie was already present
console.log('cookie exists', cookie);
}
res.redirect('/account_service/profile');
});
} catch (error) {
return next(error);
}
})(req, res, next);
});
After the user is authenticated, I assign a JSON web token to the user and place it in the cookie so it gets stored within the headers for authorized requests. Here is an example:
AccountService.js
// Get all users
router.get('/account_service/all_users', passport.authenticate('jwt', { session: false }), (req, res, next) => {
const sql = 'select * from user';
const params = [];
db.all(sql, params, (err, rows) => {
if (err) {
res.status(500).json({ error: err.message });
return;
}
res.json({
message: 'success',
data: rows
});
});
});
I use passport.authenticate to ensure that the jwt is valid. This GET request only works after I login with admin user account.
Within my passport file I have it setup like so:
passport.js
const LocalStrategy = require('passport-local').Strategy;
const db = require('../database.js');
const bcrypt = require('bcrypt');
const config = require('../config/config.js');
const JwtStrategy = require('passport-jwt').Strategy;
const cookieExtractor = function (req) {
var token = null;
if (req && req.cookies) token = req.cookies.jwt;
return token;
};
module.exports = function (passport) {
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
passport.use('local-login', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, (req, email, password, done) => {
try {
const sql = `select * from user WHERE email = "${email}"`;
const params = [];
db.all(sql, params, (err, row) => {
if (err) {
return done(err);
}
if (!row.length || !bcrypt.compareSync(password, row[0].password)) {
return done(null, false, req.flash('loginMessage', 'Inavalid username/password combination. Please try again.'));
}
return done(null, row);
});
} catch (error) {
return done(error);
}
}));
const opts = {};
opts.jwtFromRequest = cookieExtractor; // check token in cookie
opts.secretOrKey = config.ACCESS_TOKEN_SECRET;
// eslint-disable-next-line camelcase
passport.use(new JwtStrategy(opts, function (jwtPayload, done) {
try {
const sql = `select * from user WHERE email = "${jwtPayload.email}"`;
const params = [];
db.all(sql, params, (err, row) => {
if (err) {
return done(err);
}
if (!row.length || !bcrypt.compareSync('admin', jwtPayload.role)) {
return done(null, false, { message: '403 Forbidden' });
}
return done(null, row);
});
} catch (error) {
return done(error);
}
}));
};
Here's where I get confused as my test cases break. I am trying to login before my test cases to allow my other test cases to run but I end up getting a 401 error. Here are my test cases:
accountservice.test.js
const app = require('../../app');
const supertest = require('supertest');
const http = require('http');
describe('Account Service', () => {
let server;
let request;
beforeAll((done) => {
server = http.createServer(app);
server.listen(done);
request = supertest.agent(server);
request.post('/account_service/login')
.send({ email: 'admin#example.com', password: 'admin' })
.end(function (err, res) {
if (err) {
return done(err);
}
console.log(res);
done();
});
});
afterAll((done) => {
server.close(done);
});
it('Test request all users endpoint | GET request', async done => {
const response = await request.get('/account_service/all_users');
expect(response.status).toBe(200);
expect(response.body.message).toBe('success');
expect(response.body.data.length).toBe(3);
done();
});
});
But my test cases fail as I get a 401 error when it expects a 200 success code.
I tried thinking of a way to extract the jwt from a cookie after the login call so that I can set up the headers for the /account_service/all_users GET request code but was unable to find a way using Supertest. I saw this post: Testing authenticated routes with JWT fails using Mocha + supertest + passport but saw that it gets the token from the body.
After messing around with my code, I ended up having issues with in-memory storage and running asynchronous db.run functions that would call every time I ran my server. So I used a file to store my data and ran my tests again and it ended up working!
Here was the faulty code:
const sqlite3 = require('sqlite3').verbose();
const md5 = require('md5');
const DBSOURCE = ':memory:';
const db = new sqlite3.Database(DBSOURCE, (err) => {
if (err) {
// Cannot open database
console.error(err.message);
throw err;
} else {
db.run(`CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name text,
email text UNIQUE,
password text,
status text,
comments text,
photos text,
CONSTRAINT email_unique UNIQUE (email)
)`,
(err) => {
if (err) {
// Table already created
console.log('Table already created');
} else {
// Table just created, creating some rows
const insert = 'INSERT INTO user (name, email, password, status, comments, photos) VALUES (?,?,?,?,?,?)';
db.run(insert, ['user_delete', 'user_delete#example.com', md5('admin123456'), 'pending_deleted', 'comment1,comment2', 'https://giphy.com/gifs/9jumpin-wow-nice-well-done-xT77XWum9yH7zNkFW0']);
db.run(insert, ['user_no_delete', 'user#example.com', md5('user123456'), 'active', 'comment1', 'https://giphy.com/gifs/cartoon-we-bare-bears-wbb-NeijdlusjcduU']);
db.run(insert, ['mikey', 'mikey#example.com', md5('mikey123'), 'pending_deleted', 'comment1', 'https://giphy.com/gifs/wwe-shocked-vince-mcmahon-gdKAVlnm3bmKI']);
}
});
}
});
module.exports = db;
I simply stored this data within a file and used this code instead:
const sqlite3 = require('sqlite3').verbose();
const DBSOURCE = 'mockdb.sqlite';
// Data inserted inside file
/*
db.run(insert, ['user_delete', 'user_delete#example.com', bcrypt.hashSync('admin123456', saltRounds), 'pending_deleted', 'comment1,comment2', 'https://giphy.com/gifs/9jumpin-wow-nice-well-done-xT77XWum9yH7zNkFW0', bcrypt.hashSync('user', saltRounds)]);
db.run(insert, ['user_no_delete', 'user#example.com', bcrypt.hashSync('user123456', saltRounds), 'active', 'comment1', 'https://giphy.com/gifs/cartoon-we-bare-bears-wbb-NeijdlusjcduU', bcrypt.hashSync('user', saltRounds)]);
db.run(insert, ['mikey', 'mikey#example.com', bcrypt.hashSync('mikey123', saltRounds), 'pending_deleted', 'comment1', 'https://giphy.com/gifs/wwe-shocked-vince-mcmahon-gdKAVlnm3bmKI', bcrypt.hashSync('user', saltRounds)]);
db.run(insert, ['admin', 'admin#example.com', bcrypt.hashSync('admin', saltRounds), 'active', 'admincomments', 'adminphoto', bcrypt.hashSync('admin', saltRounds)]);
console.log('last hit in database');
});
*/
const db = new sqlite3.Database(DBSOURCE, (err) => {
if (err) {
// Cannot open database
console.error(err.message);
throw err;
}
console.log('Connection successful!');
});
module.exports = db;
I also ended up using supertest.agent.
const app = require('../../app');
const supertest = require('supertest');
const http = require('http');
const db = require('../../database/database.js');
describe('Account Service', () => {
let server;
let request;
// Find cookie management option.
beforeAll(async (done) => {
server = http.createServer(app);
server.listen(done);
request = supertest.agent(server);
done();
});
And it ended up working and successfully solving my issue!

How can I handle data/json that I retrieve from my API Webservice (ExpressJS)?

I'm new to NodeJS and ExpressJS. I created an AuthController which handles the login post.
exports.login = async (req, res, next) => {
try {
const email = req.body.email;
const password = req.body.password;
const user = await User.findOne({ email }).select("+password");
if (!user) {
const error = new Error("Wrong Credentials");
error.statusCode = 401;
throw error;
}
const validPassword = await user.validPassword(password);
if (!validPassword) {
const error = new Error("Wrong Credentials");
error.statusCode = 401;
throw error;
}
const token = jwt.encode({id: user.id}, config.jwtSecret);
res.send({user, token});
} catch(err) {
next(err);
}
}
I would like to use this method in my web application to let the user login. If the user succesfully logs in, I get a json response in my browser with the user and the token. That's not what I want. The url for the api login is: /api/auth/login. I created a function in my web application:
router.post('/login', async (req, res, next) => {
var apiResponse = await authController.login(req, res, next);
res.render('profile.ejs', {user: apiResponse.user});
});
I keep getting the error that authController.login is not a function. My question is how can I use the method from my API and use the response in my webapplication? Can someone help me out?
You can do it like this code below: 👇
router.post('/login', authController.login, async (req, res, next) => {
res.render('profile.ejs', {user: apiResponse.user});
});
👨‍🏫 Please read the documentation about Express Middleware.
Updated: Middleware
Make sure your authController looks like this code below:
exports.login = async (req, res, next) => {
try {
const email = req.body.email;
const password = req.body.password;
const user = await User.findOne({ email }).select("+password");
if (!user) {
const error = new Error("Wrong Credentials");
error.statusCode = 401;
throw error;
}
const validPassword = await user.validPassword(password);
if (!validPassword) {
const error = new Error("Wrong Credentials");
error.statusCode = 401;
throw error;
}
const token = jwt.encode({id: user.id}, config.jwtSecret);
// passing your data to next function
// you can change exampleData with the 'variable' you want
req.exampleData = { user, token }
next();
} catch(err) {
next(err);
}
}
If your authController is same root ("folder") with the your routes, than make it's look like this:
const { login } = require('./authController');
So, now, you can call the authController like this:
router.post('/login', login, async (req, res, next) => {
// your data: "user" and "token" from middleware
const { exampleData } = req;
console.log(exampleData);
res.render('profile.ejs', {user: exampleData});
});
I hope it's can help you 🙏.

Getting [jwt is not defined] while fetching data from MongoDB backend -

the question is pretty self explanatory. I am registering/signing up users in a mongoDB database. They are being registered fine and an accesstoken [jwt based] is also being generated.
Now, when I go to query the database to fetch the list of users I am getting that error -
jwt is not defined.
It is worthwhile to mention that users also in my backend can have two type of roles - basic and admin. And only an admin user can fetch list of all users by sending accessToken in the header as Bearer authorization parameter.
I have 2 main files in my backend project structure that uses jwt.access methods like jwt.verify or jwt.signIn; these are the server.js and userController.js [a separate file where I have written all individual db related methods].
As far as I am concerned, all necessary packages are there in my project - express, node, jwa, jws, jsonwebtoken, mongo, mongoose, bcrypt, cors etc. So what is the trouble?
My route.js -->
const User = require('../models/user.model');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const { roles } = require('../models/roles');
const JWT_SECRET = "$#GR24T4344$#$##%ETWWTEME%$6";
async function hashPassword(password) {
return await bcrypt.hash(password, 10);
}
async function validatePassword(plainPassword, hashedPassword) {
return await bcrypt.compare(plainPassword, hashedPassword);
}
exports.grantAccess = function (action, resource) {
return async (req, res, next) => {
try {
const permission = roles.can(req.user.role)[action](resource);
if (!permission.granted) {
return res.status(401).json({
error: "You don't have enough permission to perform this action"
});
}
next();
} catch (error) {
next(error);
}
}
}
exports.allowIfLoggedin = async (req, res, next) => {
try {
const user = res.locals.loggedInUser;
if (!user)
return res.status(401).json({
error: "You need to be logged in to access this route"
});
req.user = user;
next();
} catch (error) {
next(error);
}
}
exports.signup = async (req, res, next) => {
try {
const { role, email, password } = req.body;
const hashedPassword = await hashPassword(password);
const newUser = new User({ email, password: hashedPassword, role: role || "basic" });
const accessToken = jwt.sign({ userId: newUser._id }, JWT_SECRET, {
expiresIn: "1d"
});
newUser.accessToken = accessToken;
await newUser.save();
res.json({
data: newUser,
message: "You have signed up successfully"
});
} catch (error) {
next(error);
}
}
exports.login = async (req, res, next) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user)
return next(new Error('Email does not exist'));
const validPassword = await validatePassword(password, user.password);
if (!validPassword)
return next(new Error('Password is not correct'));
const accessToken = jwt.sign({ userId: user._id }, JWT_SECRET, {
expiresIn: "1d"
});
await User.findByIdAndUpdate(user._id, { accessToken });
res.status(200).json({
data: { email: user.email, role: user.role },
accessToken
});
} catch (error) {
next(error);
}
}
exports.getUsers = async (req, res, next) => {
const users = await User.find({});
res.status(200).json({
data: users
});
}
exports.getUser = async (req, res, next) => {
try {
const userId = req.params.userId;
const user = await User.findById(userId);
if (!user)
return next(new Error('User does not exist'));
res.status(200).json({
data: user
});
} catch (error) {
next(error);
}
}
exports.updateUser = async (req, res, next) => {
try {
const { role } = req.body;
const userId = req.params.userId;
await User.findByIdAndUpdate(userId, { role });
const user = await User.findById(userId);
res.status(200).json({
data: user
});
} catch (error) {
next(error);
}
}
exports.deleteUser = async (req, res, next) => {
try {
const userId = req.params.userId;
await User.findByIdAndDelete(userId);
res.status(200).json({
data: null,
message: 'User has been deleted'
});
} catch (error) {
next(error);
}
}
My server.js -->
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const PORT = 4000;
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const playerRoutes = express.Router();
const userRoutes = express.Router();
const userController = require('./controllers/userController');
const user_routes = require('./apiroutes/route');
const app = express();
const JWT_SECRET = "$#GR24T4344$#$##%ETWWTEME%$6";
const users = "users";
require("dotenv").config({path: __dirname+ '../.env'});
let Player = require('./models/player.model');
let User = require('./models/user.model');
app.use(cors());
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: false
})
);
mongoose.connect('mongodb://127.0.0.1:27017/playerDB', function (err, db) {
if (err)
throw err;
db.createCollection(users, function (err, resp) {
if (err)
throw err;
console.log("Collection created!");
});
}, { useNewUrlParser: true });
const connection = mongoose.connection;
connection.once('open', function () {
console.log("MongoDB database connection established successfully");
});
..... blablablaaaa
app.use('/playerDB', playerRoutes);
app.use(async (req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
if (req.headers["x-access-token"]) {
try {
const accessToken = req.headers["x-access-token"];
const { userId, exp } = await jwt.verify(accessToken, JWT_SECRET);
// If token has expired
if (exp < Date.now().valueOf() / 1000) {
return res.status(401).json({
error: "JWT token has expired, please login to obtain a new one"
});
}
res.locals.loggedInUser = await User.findById(userId);
next();
} catch (error) {
next(error);
}
} else {
next();
}
});
app.use('/users', user_routes);
app.listen(PORT, function () {
console.log("Server is running on Port: " + PORT);
});
I hope you understand my approach and scenario? Can you guess, where it could have gone wrong? Any idea?
Missing npm packages or something more critical?
Look forward to some hints on this problem! Can't seem to figure out a way!
it seems you forgot to add this line to server.js
const jwt = require('jsonwebtoken');
While register and login, this didn't caused a problem, because for these requests, req.headers["x-access-token"] was null, and the code didn't reach the if block where you used jwt, but one a request with this header came (like getUsers) the code tried to use jwt.verify, but since jwt wasn't imported it gave error.

Resources