Authentication with passeport in node and angular 2 - node.js

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

Related

Receiving data from backend returns undefined

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)

How to initiate session on signup with cookie-session and passport.js?

I have a /register router for signing up a user. I am using cookie-session (which is similar) instead of express-session for simplicity for now.
I am stuck on the part where I need to authenticate a user on sign up. I am confused about the functionality of req.sessions.save() and req.login(). I know req.login() is provided by passport.js, but I don't understand which one provides the req.session object.
I am new to passport.js and have read numerous articles, videos, and StackOverflow questions extensively to build up my knowledge. Honestly, the passport documentation has been quite a pain so far. I am still confused about how session initiation on signup should work. Many articles skipped the signup part. I thus request help on how to do it.
router.post('/register', (req, res, next) => {
console.log(req.body)
User.findOne({email: req.body.email}).then((currentUser) => {
if(currentUser){ // already exists
res.render('login')
} else { // if not, create user in our db
new User({
email: req.body.email
}).save().then((newUser) => {
passport.authenticate('local')(req, res, () => {
//>>>> //**This is where I don't know what to do**
req.session.save((err) => {
if (err) {
return next(err)
}
res.redirect('http://localhost:3000')
})
})
});
}
});
})
const express = require("express");
const router = express.Router();
const passport = require("passport");
router.post("/register", (req, res, next) => {
User.findOne({ email: req.body.email }).then((currentUser) => {
if (currentUser) { // already exists
res.render('login')
} else { // if not, create user in our db
new User({
email: req.body.email
}).save();
}
});
passport.authenticate("local", function (err, user, info) {
if (err) {
return res.status(400).json({ errors: err });
}
if (!user) {
return res.status(400).json({errors:"No user found."});
// or save User : new User({email: req.body.email}).save();
}
req.login(user, function (err) {
if (err) {
return res.status(400).json({ errors: err });
}
req.session.save((err) => {
if (err) {
return next(err)
}
res.redirect('http://localhost:3000')
});
return res.status(400).json({ success: `logged in ${user.id}` });
});
})(req, res, next);
});
module.exports = router;
passport.authenticate('local')(request, response, () => {
req.session.save((err) => {
if (err) {
return next(err)
}
res.redirect('http://localhost:3000')
})
}

passport.authenticate() using a Promise instead of a Custom Callback

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)
})

Set default value after Registration, StormPath

I have a simple StormPath/Express app, and AFTER a user registers, I want to set the default value for country to "World" (customData). Later on the user can change it to any country in their profile page.
How would I use the preRegistrationHandler to accomplish this (if that is the best way). Thanks.
app.use(stormpath.init(app, {
preRegistrationHandler: function (formData, req, res, next) {
console.log('Got registration request', formData);
next();
}
}));
You want to use the postRegistrationHandler to run code AFTER registration has completed =)
For instance:
app.use(stormpath.init(app, {
postRegistrationHandler: (account, req, res, next) => {
account.getCustomData((err, data) => {
if (err) return next(err);
data.country = 'World';
data.save((err) => {
if (err) return next(err);
next();
});
});
});
});

Express redirect after login authentication

I'm working on an app which has node.js and express on the server, mongodb for the db and Backbone.js on the front-end. I'm working on enabling user logins, so I've used the passport.js library. I have a problem with my login 'post' method: It is not redirecting to another page (well it's an SPA, so I mean rendering a Backbone view). Here's the code:
//standard express setup...
app.post('/api/auth', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) {
req.session.messages = [info.message];
return res.redirect('/')
}
req.logIn(user, function(err) {
if (err) {
return next(err);
} else {
console.log('yup, working'); //Can see the response in the console
return res.redirect('/api');
}
});
})(req, res, next);
});
app.get('/api', function (request, response) {
response.send( 'Login successful!' );
});
So I can see the console.log message fine, and a GET request for the route IS triggered...but nothing actually happens. So I'm thinking that I've misunderstood how 'res.redirect' works - I want to navigate to that route upon the login success. I've thought about using window.location, but is this a good long-term solution? I'm not using any html templates on the server, so I can't (I don't think) do something as simple as 'res.render('index')'
What would be the best way to approach this? Thanks in advance.
I had a face-palm moment a few days after asking this question where I realized I had failed to grasp a core concept correctly. Let me answer my own question:
Rather than trying to serve the page from the server, I just need to send a response to the client and have Backbone do the rendering, depending on the response received. So my server does something more like this:
controller.post('/user', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
user.save(function(err) {
if(err){
console.log(err);
return res.json(401);
} else {
return res.json(200); //SEND RESPONSE - do not try to redirect
}
});
Then I do the page loading in the Backbone View, like this:
login: function (e) {
e.preventDefault();
console.log('submitting login request');
var formValues = {
username: $('#inputEmail').val(),
password: $('#inputPassword').val()
};
var user = new User(); //user model
user.set(formValues);
function saveUserfunction (){
if(user) {
user.save(this.formValues, {
success: function(model, response, options) {
if (response == 200) {
console.log('success :' + response);
window.location.href = 'http://localhost:4711/#/api/menu_auth'; //Here's my redirect - the router is listening for this route and will render accordingly
} else {
console.log('error: '+response);
}
}, error: //Error handling etc.
As Pheonix pointed out in the comments, the best way to do this would be to listen to the the user model.

Resources