I am trying to fetch some data from my server and when testing the request with Postman it works great and I getting data back. But then when I trying to implement the request in my app Im getting back an empty object with undefined properties
CODE:
fetchUserData = (user) => {
axios.post('api', {
username: user
})
.then((res) => {
this.setState({
credit: res.credit,
points: res.points
})
console.log(`this is user stats\ncredit:${res.credit}\npoints:${res.points} for the user: ${user}`)
})
}
router.post('/', (req, res) => {
UserData.findOne({
username: req.body.username,
},
(err, user) => {
if (err) {
console.log('Error in saving user to mongodb: ' + err);
res.send(err);
}
if (user) {
if(user.username === req.body.username) {
console.log('fetching data for: ' + user.username);
console.log(user);
res.send(user);
}
}
});
})
RESPONSE FROM POSTMAN:
{"_id":"5afd9bXXXXXXX664a5af","username":"check","credit":1,"points":0,"__v":0}
RESPONSE ON APP CONSOLE:
this is user stats credit:undefined points:undefined for the user: check
to read data from the response I should have to use 'res.data.something' and not res.something
Related
This is my code for getting user info
router.post("/getuser", fetchuser, async (req, res) => {
try {
userId = req.user.id;
const user = await User.findById(userId).select("-password");
res.send(user);
} catch (error) {
console.error(error.message);
res.status(500).send("Internal Server Error");
}
});
and this is the code for middleware fetchuser
const fetchuser = async (req, res, next) => {
const token = req.header('auth-token');
if (!token) {
res.status(401).send({ error: "Please authenticate using a valid token" })
}
try {
const data = jwt.verify(token, process.env.SECRET);
console.log(data);
req.user = data.user;
next();
} catch (error) {
res.status(401).send({ error: "Please authenticate using a valid token" })
}
};
I am getting the user id in console.log but when I try to get the user id in the router.post then I am not able to get the user Info.
Here is the result I am getting.
Server is running on port 5000
Connected to database
{ id: '61e98c45a9d8818292b38505', iat: 1642743501 }
Cannot read properties of undefined (reading 'id')
Please can anyone tell me what is wrong with this?
router.post("/getuser", fetchuser, async (req, res) => {
try {
const params = JSON.parse(req)
userId = params.id;
const user = await User.findById(userId).select("-password");
res.send(user);
} catch (error) {
console.error(error.message);
res.status(500).send("Internal Server Error");
}
});
Your code is working fine , you just have to change this line on fetchuser middleware
req.user = data.user
to
req.user = data
and your code work as expected..
add file: src/types/express/index.d.ts
content:
declare namespace Express {
interface Request {
user: {
id: string;
};
}
}
I want to make a middleware to check the user. I'm using JWT and cookies for this. I retrieved the cookie and decrypted it (it has been encrypted in the login controller function). Then I used jwt.verify(). But I've received this error message : JsonWebTokenError: jwt malformed.
I've seen that it may mean that the token wasn't "the right formated" one. But I can't figure it out.
checkUser function :
exports.checkUser = async(req, res, next) => {
const cryptedToken = req.cookies.snToken;
console.log("cryptedToken01", cryptedToken); //displays a string consists of 3 parts, separated by /
const token = cryptojs.AES.decrypt(cryptedToken, process.env.COOKIE_KEY).toString();
console.log("token01", token); // displays a longer monolithic string
if (token) {
jwt.verify(token, process.env.COOKIE_KEY, async(err, verifiedJwt) => {
if (err) {
console.log("err inside jwt verify", err); // displays an error mesassage (JsonWebTokenError: jwt malformed)
console.log("res.locals", res.locals); //displays res.locals [Object: null prototype] {}
res.locals.user = null;
res.cookie("snToken", "", { maxAge: 1 });
next();
} else {
let user = await User.findByPk(verifiedJwt.userId);
res.locals.user = user;
next();
}
});
} else {
res.locals.user = null;
next();
}
};
my login function :
exports.login = async(req, res) => {
try {
const user = await User.findOne({ where: { email: req.body.email } });
if (!user) {
return res.status(403).send({ error: 'The login information (email) is incorrect!' });
}
bcrypt
.compare(req.body.password, user.password)
.then((isPasswordValid) => {
if (!isPasswordValid) {
return res.status(403).send({ error: 'The login information (pwd) is incorrect!' });
} else {
const newToken = jwt.sign(
{ userId: user.id },
process.env.COOKIE_KEY, { expiresIn: "24h" }
);
const newCookie = { token: newToken, userId: user.id };
const cryptedToken = cryptojs.AES.encrypt(JSON.stringify(newCookie), process.env.COOKIE_KEY).toString();
res.cookie('snToken', cryptedToken, {
httpOnly: true,
maxAge: 86400000
});
//res.status(200).send({ message: 'The user is successfully connected!', data: user });
res.status(200).send({ message: 'The user is successfully connected!', data: user, cryptedToken: cryptedToken });
}
});
} catch (error) {
res.send({ error: 'An error has occured while trying to log in!' });
}
}
The call of these middlwares in my app.js:
app.get('*', checkUser);
In your current code, you get a Hex encoded ASCII string after decryption
7b22746f6b656e223a2265794a68624763694f694a49557a49314e694973496e523563434936496b705856434a392e65794a3163325679535751694f6a45314c434a70595851694f6a45324e4445314e6a45324d545173496d5634634349364d5459304d5459304f4441784e48302e693670564f486443473456445154362d3749644545536f326251467765394d4b34554a316f363676564334222c22757365724964223a31357d,
which contains your cookie as a stringified JSON.
Instead of toString() after decrypting, which causes the hex encoded output, call toString(cryptojs.enc.Utf8) to get a JSON String and then parse it to an object:
const bytes = cryptojs.AES.decrypt(cryptedToken, process.env.COOKIE_KEY);
const cookie = JSON.parse(bytes.toString(cryptojs.enc.Utf8));
console.log("token", cookie.token);
the result is a correct JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjE1LCJpYXQiOjE2NDE1NjE2MTQsImV4cCI6MTY0MTY0ODAxNH0.i6pVOHdCG4VDQT6-7IdEESo2bQFwe9MK4UJ1o66vVC4
I'm making a simple backend API but I keep getting this error when I try to post:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
The first part of the code seems to run but I'm not sure why the rest is erroring. I've tried many solutions and they don't seem to work. I think I'm doing something incorrectly. Any help would be appreciated.
Here is my code:
import { Router } from 'express';
import bcrypt from 'bcryptjs'
import fetch from 'node-fetch';
const router = Router(),
A = require('../../models/A');
router.post('/a/:n/:username', (req, res) => {
bcrypt.genSalt(10, (err, salt) => {
if (err) return res.json({ message: 'error' })
bcrypt.hash(req.params.key, salt, (err, hash) => {
if (err) return res.json({ message: 'error' })
if (req.params.n !== hash) return res.json({ message: 'no access' });
})
})
fetch(`https://api.mojang.com/users/profiles/minecraft/${req.params.username}`)
.then(res => res.json())
.then(json => {
if (!json) return res.json({ message: 'Invalid user.' });
A.findOne({ id: json.id }).then((id) => {
if (id) {
res.json({ id: id.id });
} else {
const a = new A({
id: json.id,
created: Date.now()
})
a.save()
res.json({ id: json.id })
}
})
});
})
export default router;
router.post('/a/:n/:username', (req, res) => {
bcrypt.genSalt(10, (err, salt) => {
if (err) return res.json({ message: 'error' })
bcrypt.hash(req.params.key, salt, (err, hash) => {
if (err) return res.json({ message: 'error' })
if (req.params.n !== hash) return res.json({ message: 'no access' });
//Do the fetch here
})
})
The erreor is because execution goes into bcrypt.has callback AND fetch. So the same request has more than one res.json,
We're trying to integrate Passport authentication with out React app, and we're using React Router.
On the first submission of correct user credentials, the server receives the post, adds a session to our database, and seems to send a response, but the client doesn't update. The username and password show up in the url as a query string. Then when we resend the credentials without removing the query string from the url, the client is able to receive the response from the server.
In other words, if we don't refresh before submitting the login info again, it works.
This is the click handler that our form utilizes:
const handleClick = () => {
return axios.post('/login', { username, password })
.then(({ data }) => {
const { message } = data;
if (message === 'success') {
const { user } = data;
setUserId(user.id);
setUser(user);
}
setAuthStatus(message);
})
.catch(err => console.error(err));
};
This is our server route that is hit on every post request:
loginRouter.post('/', (req, res, next) => {
console.log('stop');
passport.authenticate('local', (err, user, info) => {
const { invalidPassword } = info || false;
if (err) {
return next(err); // will generate a 500 error
}
if (!user) {
return res.send({ message: 'invalidUser' });
}
if (invalidPassword) {
return res.send({ message: 'invalidPassword' });
}
req.login(user, loginErr => {
if (loginErr) {
return next(loginErr);
}
return res.send({ user, message: 'success' });
});
})(req, res, next);
});
This is our Passport Local Strategy that uses Sequelize:
passport.use(new LocalStrategy(
(username, password, cb) => {
User.findOne({ where: { username } })
.then((user) => {
if (!user) {
return cb(null, false);
}
if (validPassword(password, user.hash, user.salt)) {
return cb(null, user);
}
return cb(null, false, { invalidPassword: true });
})
.catch(err => {
cb(err);
});
},
));
Having trouble debugging this... We suspect the error is on the client side and may have to do with React-Router. We are using React-Router and Passport for the first time on this project.
Any help is appreciated!
Welp... All we were missing was event as a parameter in handleClick and event.preventDefault().
When i trying to run my API in postman it is working fine and sessions are getting maintained. But when i am trying to run it from UI Part the login session is not working.
This is my Login API from where i am login into
app.post('/user/login', (req, res, next) => {
const body = req.body;
let email = body.email;
let password = body.password;
const userDetails = db.collection(userProfiles);
userDetails.findOne({email: email}, function (err, user) {
if (err) {
return next(err);
} else if (!user) {
return res.status(400).send({
status: 'error',
message: 'user does not exist'
});
} else {
if (user.password == password) {
user_object = user;
req.session.user = user;
return res.send({
user_obj: user,
status: 'success',
message: 'Successfully logged in'
});
} else {
return res.status(400).send({
status: 'error',
message: 'Wrong Password'
})
}
}
return res.send(user);
});
});
This is my session API from where i am sending user req.session.user on calling this api
app.get('/user/dashboard', function (req, res) {
if (!req.session.user) {
return res.status(400).send({
data:'need to be logged in'
});
}
return res.status(200).send({
data:req.session.user
});
});```
The below is the javascript file from where i am trying to call the user stores in req.session.user
`
async function fetchUserId(){
let cookie = document.cookie;
let res = await fetch('http://127.0.0.1:8080/user/dashboard',
{redirect: 'follow',
headers:{
"Cookie":cookie
}});
let userJson = await res.json();
console.log(res);
console.log(userJson);
//return userJson;
};
`
when i hit the login API from Postman it is maintaining session and working fine but when i do the same from UI from browser it is giving error status 400 every time.
You can do a
fetch(url, options).then(function(res) { console.log(res} )
and
app.get('/user/dashboard', function (req, res) {
console.log(req.headers)
if (!req.session.user) {
return res.status(400).send({
data:'need to be logged in'
});
}
return res.status(200).send({
data:req.session.user
});
});
To check is the cookie really there and where is the user object.
And you can check your browsers dev console to see if the cookie is updating.
I see that is fetch request you put a cookie in your header. But than at the API you are looking for a user at req.session.user. Although the cookie is in req.header["Cookie"].