Jsonwebtoken verify next function not working in middleware - reactjs

I was working with jsonwebtoken. Then I go to verify jsonwebtoken I see some tutorial. But when I am using my next () function I am not getting my expected data
I would have benefited from your help. Thanks
// This is for verifying the jsonwebtoken
function verifyJwt(req, res, next) {
const authHeaders = req.headers.authorization;
if (!authHeaders) {
return res.status(401).send({ message: "Unauthorized access" });
}
const token = authHeaders.split(" ")[1];
// verify a token symmetric
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, function (err, decoded) {
if (err) {
return res.status(403).send({ message: "Forbidden Access" });
}
req.decoded = decoded;
next();
console.log(decoded);
});
console.log(token);
}
//This one is for giving access if the email matched then it will give me the needed data
app.get("/booking", verifyJwt, async (req, res) => {
const patientEmail = req.query.patientEmail;
// Left over
const decodedEmail = req.decoded.patientEmail;
if (patientEmail === decodedEmail) {
const query = { patientEmail: patientEmail };
const services = await bookingCollection.find(query).toArray();
// const authorization = req.headers.authorization;
console.log(authorization);
return res.send(services);
} else {
return res.status(403).send({ message: "Forbidden Access" });
}
});
This next() function not working any solve ?

Please try the below code
try {
const decoded = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET);
req.decoded = decoded;
console.log(decoded);
next();
} catch (ex) {
return res.status(403).send({ message: 'Forbidden Access' });
}

appointments.map is not a function. Please console appointment and see what it returns.

Problem Solved
Thanks Everyone

Related

How to Check if the user is logged in on reactjs using JWT

Im trying to make a system that it can check it the user is logged of not im using reactjs and JWT tokens that can stored to the cookies in browser.
This is my reactjs file code
const ApproveRequest = (approveOption) => {
if (approveOption === "approve"){
let request = 1;
axios.put("http://localhost:3001/cash/approverequest",{
approved: request,
id: id,
header: { accessToken: cookies.getItem("accessToken") },
withCredentials: true,
}).then((response) => {
if(response.data.error) {
console.log(response.data.error);
}else{
setCashObject({ ...cashObject, request: request });
alert("Request Approve");
}
});
} else {
alert("Field to update the request please contact the dev");
}
}
from my server JWT.js file
const validateToken = (req, res, next) => {
const accessToken = req.header("accessToken");
if(!accessToken) {
return res.json({error: "User not authenticated"});
}
try{
const validToken = verify(accessToken, "bluedragon14S");
if(validToken){
req.authenticated = true;
return next;
}
}catch (err) {
return res.json({error: err});
}
}
from server cash.js route
router.put("/approverequest", validateToken,async (req, res) => {
const { request = 1, id } = req.body;
await Cash.update({request: request}, {where: {id: id} });
res.json(request);
});
I wanted is i want to check if the user is logged in so that he/she can update the request
thank you in advance for your help
Addition in that code i can store the cookies into the browser i just don't know how to check if the user is logged in or not
I think you can access user cookies in this way :
req.cookies.accessToken
so change this :
const accessToken = req.header("accessToken");
to this :
const accessToken = req.cookies?.accessToken
if(accessToken )
...

Why is a user able to login and have a json web token is issued even though user has entered incorrect password?

1.below are the AuthRoutes.js , User.js , RequireAuth.js files with the code.
2.Ive tried changing the email to an invalid un-captured one , and it does report the error "Invalid email or password" which is correct, however when the user enters the incorrect password for that user ,
3. a JSON web token is issued instead of posting the error invalid Email or password as indicated in the code.
const express = require('express');
const mongoose = require('mongoose')
const jwt = require('jsonwebtoken');
const User = mongoose.model('User');
const router = express.Router();
router.post('/signup', async (req,res)=>{
const {name,email,password} = req.body;
try{
const user = new User({name,email,password});
await user.save();
const token = jwt.sign({ userId: user._id},'MY_SECRET_KEY');
res.send({token});
} catch (err) {
return res.status(422).send(err.message);
}
});
router.post('/signin', async (req, res) =>{
const { email, password} = req.body;
if (!email || !password) {
return res.status(422).send({error:'Must provide email and password '})
}
const user = await User.findOne ({ email});
if(!user) {
return res.status(422).send ({error:'Invalid email or password'});
}
try{
await user.comparePassword(password);
const token = jwt.sign ({userId: user._id},'MY_SECRET_KEY');
res.send ({ token });
} catch (err){
return res.status(422).send({error:'Invalid password or email'})
}
});
module.exports = router;
const jwt = require ('jsonwebtoken');
const mongoose = require ('mongoose');
const User = mongoose.model('User');
module.exports = (req,res,next) =>{
const {authorization} = req.headers.body;
//authorization === 'Bearer dfkndlkfgdkgmdlkgmdlkgdkfgmdlfkg(token)'
if (!authorization) {
return res.status (401).send ({error:"You must be logged in"});
}
const token = authorization.replace('Bearer ','');
jwt.verify(token, 'MY_SECRET_KEY', async (err, payload)=>{
if (err){
return res.status(401).send({error:'You must be logged in'});
}
const {userId} = payload;
const user = await User.findById(userId);
req.user = user;
next();
});
};
const mongoose = require('mongoose');
const bcrypt = require ('bcrypt');
const userSchema = new mongoose.Schema({
name:{
type:String,
required: true,
},
email:{
type: String,
unique: true,
required: true,
},
password:{
type:String,
required: true
}
});
userSchema.pre('save', function (next){
const user = this;
if(!user.isModified('password')){
return next();
}
bcrypt.genSalt(10, (err,salt) =>{
if (err){
return next (err);
}
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) {
return next (err);
}
user.password = hash;
next ();
});
});
});
userSchema.methods.comparePassword = function(candidatePassword){
return new Promise ((resolve,reject) => {
bcrypt.compare (candidatePassword, this.password, (err,isMatch) => {
if (err){
return reject (err);
} else {
return resolve(true);
}
});
});
};
mongoose.model('User', userSchema);
Its because your comparePassword is returning a result that isn't checked for / caught.
Change your promise to:
return new Promise ((resolve,reject) => {
bcrypt.compare(candidatePassword, this.password, (err, res) => {
if (err){
reject(err);
} else {
resolve(res);
}
});
});
And then your check to:
const result = await user.comparePassword(password);
if (!result) return res.status(422).send({error:'Incorrect email and/or password'});

JWT gives invalid token

Working locally, my jwt token is invalid but in jwt.io it shows verified signature. Not sure what i am missing. I am having invalid signature whenever i tried to make a call to a api whithin the app.
Link.js
const { Router } = require("express");
const Link = require("../models/Link");
const auth = require("../middleware/auth.middleware");
const router = Router();
router.get("/", auth, async (req, res) => {
try {
const links = await Link.find({ owner: req.user.userId });
res.json(links);
} catch (error) {
res.status(500).json({ message: "Something went wrong, try again" });
}
});
auth.middleware.js
const jwt = require("jsonwebtoken");
const config = require("config");
module.exports = (req, res, next) => {
if (req.method === "OPTIONS") {
return next();
}
try {
const token = req.headers.authorization; // Token
if (!token) {
return res.status(401).json({ message: "No Authorization" });
}
const decoded = jwt.verify(token, config.get("secret"));
req.user = decoded;
next();
} catch (error) {
res.status(401).json({ message: "No Authorization" });
}
};
Links.tsx
const LinksPage: React.FC = () => {
const [links, setLinks] = useState([]);
const fetchLinks = useCallback(async () => {
try {
const fetched = await request("http://localhost:5000/api/link/", "GET", null, {
Authorization: Token,
});
setLinks(fetched);
} catch (error) {
alert(error);
}
}, []);
};
Maybe the "req.headers.authorization" was not what you looking for.
Try to console.log(req.headers.authorization) F12 in chrome, firefox.
I suggest you also POSTMAN (free software). It help me a lot for debugging the back end (server side).
I solved the problem. I had to json.parse(token) which stored in the client in order to jwt.verify(token, secret), but instead i was verifying string that contains object of token and userId.

express generate json file on the fly

I have a rest api (expressjs) which handles user personal records.
I want to create a route that will allow a user to download all of its records in a json file(the file should be generated on the fly and not be stored on the server_.I found the following gist:
app.get('/', function(req, res) {
res.contentType('text/plain');
res.send('This is the content', { 'Content-Disposition': 'attachment; filename=name.txt' });
});
Which I modified to this:
router.get('/records/export', validateToken, async (req, res, next) => {
const id = res.locals.user;
try {
const user = await User.findById(id).exec();
const {
records
} = user;
res.contentType('json');
res.statusCode = 200;
res.send(JSON.stringify(records), {
'Content-Disposition': `attachment; filename=record-backup-${user.email}`
});
} catch (e) {
next(e);
}
});
However when I try to hit that endpoint I get the following error
RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code:
Any ideas what I am doing wrong?
Try giving it the status code like this:
res.status(200).send(JSON.stringify(records), {
'Content-Disposition': `attachment; filename=record-backup-${user.email}`
});
So I finally figured out what was wrong with my code.
res.send accepts only one argument.So I used res.set to set content-disposition header and my working code is this:
router.get('/records/export', validateToken, async (req, res, next) => {
const id = res.locals.user;
try {
const user = await User.findById(id).exec();
const {
records
} = user;
res.contentType('application/octet-stream');
res.set('Content-Disposition', `attachment; filename=record-backup-${user.email}`)
.status(200).send(JSON.stringify(records));
} catch (e) {
next(e);
}
});

set current user in context using apollo server

i have this middleware and need to get current user to set it in context of apollo server
app.use(async (req, res, next)=>{
const token = req.headers['authorization'];
if(token !== "null"){
try {
const currentUser = await jwt.verify(token, process.env.SECRET)
req.currentUser = currentUser;
} catch (error) {
console.log(error);
}
}
next()
})
and need to set current user in context
const SERVER = new ApolloServer({
schema,
context:{
currentUser //need to set this current user
}
})
SERVER.applymiddleware({app})
the context api in Apollo server offers handling request as follows
const initGraphQLserver = () => {
const graphQLConfig = {
context: ({ req, res }) => ({
user: req.user,
}),
rootValue: {},
schema,
};
const apolloServer = new ApolloServer(graphQLConfig);
return apolloServer;
};
This will assume that you will have proper middleware that will parse the cookie or header. This is dependent on your authentication mechanism as you need to have set user for the request in some middleware before, if you would like to use JWT, you can use for example this middleware
const auth = (req, res, next) => {
if (typeof req.headers.authorization !== 'string') {
return next();
}
const header = req.headers.authorization;
const token = header.replace('Bearer ', '');
try {
const jwtData = jwt.verify(token, JWT_SECRET);
if (jwtData && jwtData.user) {
req.user = jwtData.user;
} else {
console.log('Token was not authorized');
}
} catch (err) {
console.log('Invalid token');
}
return next();
};
This middleware will inject user if the jwt token is correct, then in your server file you will need to have the following order of middlewares
const app = express();
app.use(auth);
initGraphQLserver().applyMiddleware({ app });
Now you should have user in your schema context. I hope that it is clear, the code is not completed, but should be easy to finalize everything.

Resources