In the node.js in the login post endpoint, I get the login data for user. I declare req.user.dataValues in variable userData and I'm trying to access it inside /data endpoint so later I can access it on frontend.
Node.js - localhost:4000
router.post('/login', function (req, res, next) {
passport.authenticate('local', function (err, user, info) {
if (err) {
return next(err)
} else if (!user) {
console.log('message: ' + info.message);
return res.redirect('/login')
} else {
req.logIn(user, function (err) {
if (err) {
return next(err);
}
let userData = req.user.dataValues;
router.get('/data', (req, res) => {
console.log(userData)
res.json({user: userData})
})
res.json({ redirectUrl: "app", user: req.user.dataValues});
});
}
})(req, res, next);
});
I'm using the code below to fetch the data from the /data endpoint from node.js. I don't get any errors but the result is undefined, I wonder why? I need this data in my frontend to build the login etc.
react.js - localhost:3000
Testing = () => {
fetch("http://localhost:4000/data")
.then(res => console.log(res.json()))
.then(
(result) => {
console.log(result)
},
(error) => {
console.log(error)
}
)
}
I ran some test on express. Looks like you are defining your /data endpoint the wrong way.
You are defining the endpoint inside an anonymous function hence it exists only inside the scope of the function.
You should move
router.get('/data', (req, res) => {
console.log(userData)
res.json({user: userData})
})
outside the router.post('/login)
Related
In the following segment of code, I place a call to a microservice using axios.
app.get('/api/user/microservice/signin', async (req, res) => {
console.log('USER SIGNIN BEGINS')
try {
const user = await axios.post('http://localhost:4210/usermicroservice/signin', req.body)
console.log('USER CONTROLLER user from mongo ', user)
res.send(user);
} catch (error) {
throw error;
}
});
The target function is invoked, the data is retrieved from the database but the result never gets to the calling function. They system just hangs.
The called function:
app.post('/usermicroservice/signin', async (req, res) => {
console.log('\n*** USER MICROSERVICE SIGNIN CALLED ***')
let user = await UserMicroservice.signin(res, req.body);
console.log('user from mongo ', user)
// res.status(200).json({user})
return user;
});
UserMicrosevice.signin() returned value:
if (await PasswordUtil.check(user.password, existingUser.password) == true) {
existingUser.token = PasswordUtil.generateAccessToken(existingUser, user.password);
console.log('existingUser token', existingUser.token)
console.log('existingUser', existingUser)
delete existingUser.password;
let credentials = { name: existingUser.name, email: existingUser.email, token: existingUser.token };
return credentials;
}
CORS:
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
next();
})
After a while we figured it out, the microservice response should be:
app.post('/usermicroservice/signin', async (req, res) => {
console.log('\n*** USER MICROSERVICE SIGNIN CALLED ***')
let user = await UserMicroservice.signin(res, req.body);
console.log('user from mongo ', user)
res.status(200).json({user})
});
passport.authenticate(), how can I define a Promise instead of using a Custom Ballback?
How to used passport.authenticate() is referenced within here:
http://www.passportjs.org/docs/authenticate/
Within this page, there is a section Custom Ballback:
If the built-in options are not sufficient for handling an authentication request, a custom callback can be provided to allow the application to handle success or failure.
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
The Custom Callback is defined as:
function(err, user, info){...}
What I wish to do is replace this Custom Callback with a Promise.
[Promise](resolve, reject)
.then(res => {
})
.catch(err => {
})
How can I do this? Thank you.
You can use the es6-promisify package. It is very easy to use, here is an example:
const {promisify} = require("es6-promisify");
// Convert the stat function
const fs = require("fs");
const stat = promisify(fs.stat);
// Now usable as a promise!
stat("example.txt").then(function (stats) {
console.log("Got stats", stats);
}).catch(function (err) {
console.error("Yikes!", err);
});
Thanks all for your helpful responses #sterling-archer and #el-finito
I had found a related issue within Passport.js Github repository helpful for using Passport to handle passport.authenticate() callback:
"Using node's promisify with passport"
export const authenticate = (req, res) =>
new Promise((resolve, reject) => {
passport.authenticate(
[passport strategy],
{ session: false },
(err, user) => {
if (err) reject(new Error(err))
else if (!user) reject(new Error('Not authenticated'))
resolve(user)
})(req, res)
})
I'm trying to build an angular 2 application,here is my backend implementation
router.post('/', function(req, res, next) {
passport.authenticate('local', function (err, user, info) {
var error = err || info;
if (error) return res.json(401, error);
if (!user) return res.json(404, {message: 'Something went wrong, please try again.'});
var token = auth.signToken(user._id, user.role);
res.json({token: token});
})(req, res, next)
});
now i want to implement my frontend side with angular 2 but i have no idea how to code services and components.
i tried this
Login(user) {
return new Promise((resolve, reject) => {
this.http.post('http://localhost:3000/auth/local', user)
.map(res => res.json())
});
any solution?
have you looked at this https://github.com/domfarolino/angular2-login-seed
as well as https://github.com/domfarolino/angular2-login-seed/tree/master/src/app/login
Should be fairly easy to implement on you side
I am new to Node.JS coming from a Java Background I am using express to build this Rest API . What I am trying to do is build the concept of a manager. I am looking for a elegant way of returning a user object in the following:
users route: user.js
router.get('/find/:email', function(req, res, next){
userWare.findUserByEmail(req, res, next)
});
middleware/manager: usermiddleware.js
module.exports = {
findUserByEmail: function(req, res, next) {
models.core_user.find({
where:{
email: req.params.email
}
}).then(function(user){
res.json(user)
}, function(err){
res.status(404).json(err);
});
},
}
So In this above function I would like to return the user object to the route instead of the json. so that I can create the json from the object in the route. The whole point of this manager class will be to fectch and return objects.
What you need to do is call the callback function with the data you need or return the promise.
Callback
user.js
router.get('/find/:email', function (req, res, next) {
userWare.findUserByEmail(req.params.email, function (err, data) {
// error as first parameter or null if no error occurred
if (err) {
return res.status(404).json(err);
}
res.json(user);
});
});
usermiddleware.js
module.exports = {
findUserByEmail: function (email, next) {
models.core_user.find({
where: {
email: email
}
}).then(
function (user) {
// async call of callback with user object
next(null, user);
},
function (err) {
// async call of callback with error
next(err);
}
);
}
};
Promise
You could also just return the promise returned by your model, then it would look like this:
user.js
router.get('/find/:email', function (req, res, next) {
userWare.findUserByEmail(req.params.email).then(
function (user) {
res.json(user);
},
function (err) {
res.status(404).json(err)
}
);
});
usermiddleware.js
module.exports = {
findUserByEmail: function (email) {
// return the promise to the caller
return models.core_user.find({
where: {
email: email
}
});
}
};
I am using nodejs for a project,now I want login my account with passport npm,but not from webpage,from request post method,can it be done?
main code like this:
router.post('/login',function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.json(null); }
req.logIn(user, function(err) {
if (err) { return next(err); }
//return res.redirect('/'); redirect not work
});
})(req, res, next);
});
router.get('/check',function(req, res, next) {
request.post({
url:'http://localhost/login',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
form:{
username:'myname',
password:'mypassword'
}},function(err,httpRes,body){
//do here...?
return res.redirect('/');
});
});
When I call "check" with get method and use the correct username/password,I can print out the user data from database in "login" method,but lost the user session when it redirect home page.Any suggestion?
It's not redirecting the user when they GET /check because the POST request to /login in /check is getting redirected itself, not the actual user. Also making internal requests to internal webpages isn't the best solution for logging in. I suggest creating login() middleware like so:
// Don't forget to set req.body.username and req.body.password when calling login().
var login = function login(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return next(); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return next(null);
});
})(req, res, next);
};
And then calling it appropriately:
router.post('/login', login, function(req, res, next) {
if (req.user) {
console.log('We logged in successfully!');
res.redirect('/');
} else {
res.json(null);
}
});
router.get('/check', function(req, res, next) {
if (!req.user) {
login(req, res, function(err) {
if (err) {
return next(err);
}
if (!req.user) {
// No user, do some error handling.
} else {
// We have the user, do some custom stuff...
}
res.redirect('/');
});
} else {
// User is logged in already, do some other custom stuff...
}
});
You can check if a user is logged in by checking if req.user exists.