Authentication when using angularjs and passportjs - angularjs

I am currently using passportjs for authenticaton.
I have come across a stage where i need to ensure the user is authenticated if the url is typed in the browser/ I have been using the passportja example which has the following:
app.get('/admin', ensureAuthenticated, function(req, res){
console.log('get admin');
res.render('admin', { user: req.user });
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) { return next(); }
res.redirect('/login')
}
I am using angularjs for routing so my get does not work and run the ensure authenticated.
How should this be implemented?

With AngularJS, you need to restrict the display of templates to the user.
So, let us say you have the following code in AngularJS:
$routeProvider.when('/admin', {
templateUrl: '/partials/admin-page.html'
});
When the user tries the /admin route, AngularJS will then request the template /partials/admin-page.html.
Thus, in your nodeJs server, you then implement the following code:
app.get('/partials/admin-page.html', ensureAuthenticated, function (req, res) {
res.render('admin', { user: req.user});
});

Related

Take user back to previous page after logging in (Node)

I want to be able to redirect unauthenticated users from an individual post's page to the login and then back to the post after the user has logged in.
My login route is like this:
router.get('/login', function(req, res, next){
if (req.user){
res.redirect('/wall');
} else {
res.render('login');
}
});
My wall router looks like this:
router.get('/wall', function(req, res, next){
res.render('wall');
});
The post URL will be something like:
http://thisisnotarealdomain.com/wall#/post/ID
My stack is: NodeJS and Angular for the SPA
How do I do that?
Thanks,
First of all, I would create a middleware function to handle the redirection in case the user is not logged in, something like this:
const checkLogin = (req, res, next) => {
// Checks if the user is logged in
if(!userIsLoggedIn) {
// If user is not logged in
// Get relative path of current url
const url = req.originalUrl;
// And redirect to login page, passing
// the url as a query string that Angular
// can access later
res.redirect(`/login/?redirect=${url}`);
} else {
// If user is logged in
// go on and render the page
next();
}
}
router.get('/wall', checkLogin, function(req, res, next){
res.render('wall');
});
This way, if the user is not logged in, you would get redirect to an url like
/login/?redirect=/wall/post/14.
Then in your Angular code, you would wait for the login promise from Node and simply do a redirect to that query string we have: redirect. Something like this:
// Assuming you're logging from a service
angular
.service('LoginService', function($location, $window) {
// Generic login (could be $http, $resource, restangular)
LOGIN_PROMISE
.then(function(res) {
// If login was successful
if(res.success) {
// $location.search() allows you
// to access query strings
var redirectTo = $location.search().redirect;
// And then redirect to the page the
// user were before being redirected
// to the login page
$window.location.href = redirectTo;
}
})
})
Or you could do a redirect directly from your backend code:
// On your Angular code
$http({
method: 'GET',
params: {
redirect: $location.search().redirect
}
});
// On Node
router.get('/api/login', (req, res, next) => {
if(passwordIsCorrect) {
// And do the redirect
res.redirect(req.body.redirect);
}
});
This is just one of a lot of ways you can achieve this (that's the beauty of web development).
Hope this may help you!

node redirect not working on angular

hi I'm new to node and I'm building a simple MEAN stack app, to reduce the code I'm sending front end files like this
app.use(express.static(path.join(__dirname, 'public')));
i have also build a simple middleware for simple authentication
requireLogin = function (req, res, next) {
if (!req.user) {
console.log('redirecting :)');
res.redirect('/');
} else {
next();
}
};
app.use('/rooms',requireLogin);
I'm trying to use this middleware on routes made in angular.
but this is not working when i navigate through my angular app (it works when i directly put the URL to the address bar) i have also removed the /#/ which is added by angular.
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
I'm using ui-router for routing.
You should do redirecting on angular, but not on node.js application. For example,
requireLogin = function (req, res, next) {
if (!req.user) {
console.log('User does not exist.');
return false;
//
} else {
next();
}
};
app.use('/rooms', requireLogin);
Then, /rooms won't be able to access unless there is user logged-in.
Backend routes (express ones): Those are the routes that an end user won't have to know about or even use them (your angular app will use them to communicate with the backend to work with its data but an end user wouldn't put them directly on the browser)).
Frontend routes (angular ones): Are the routes that maps to different pages of your application and because of that, end users can use them to access some parts of your application directly.
Read Express.js or angular for handling routes in a MEAN application? for more details.

Angular authentication using Passport for Ionic App

I've built an API for my web app, which is built using MEAN stack.
Now I am trying to use this API on mobile client side which is built using Ionic Framework.
I'm using this code to perform an $http call to API:
$http.post(ServerIP+'/login', {username: $scope.credentials.username, password: $scope.credentials.password}).success(function(response) {
$scope.authentication.user = response;
$location.path('/');
}).error(function(response) {
$scope.error = response.message;
});
It gets a valid response with user object, but if I try to get some info from protected parts of an API it doesn't work and auth is being reset.
On web app, I use the same code and everything works fine.
This issue happens only on Ionic app.
I've set the CORS like that:
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
// intercept OPTIONS method
if ('OPTIONS' === req.method) {
res.sendStatus(200);
}
else {
next();
}
});
Please, help me!
Try adding this line in your angular config:
app.config(function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;
});
I've solved this problem by adding Token-Based Authentication.
Here's the article which shows how to do that: https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
Sample of my "login" route:
router.post('/login', passport.authenticate('local'), function(req, res, next){
if (req.user) {
var token = jwt.sign(req.user, secret, {expireInMinutes: 60*24*7});
res.json(token);
};
});
For getting user object on protected routes, I'm using expressJwt({secret: secret}) middleware.

passport.js auth0 strategy Cross rigin request error

I am trying to use auth0 for social validation in my web app
i configured the app like this
auth0 : {
domain : "mydomain",
clientID : "myid",
clientSecret: "mysecret",
callbackURL: "/callback"
},
I request login from angular controller using http get to node backend like
app.get('/auth/:connection', function(req, res, next) {
passport.authenticate('auth0', {connection: req.params.connection}, function(err, user, info) {
}) (req, res, next);
});
I will call like auth/facebook for facebook login from angular client side controller.
The callback route is configured like this
app.get('/callback', passport.authenticate('auth0', { failureRedirect: '#!/authServiceImpl/login' }),
function(req, res) {
console.log('auth0 callback');
console.log(req.user);
}
);
Every time I am getting Cross origin request error.
What I am doing wrong ?
I request login from angular controller using http get to node backend like
You cannot perform OAuth over XHR. Instead of doing $http.get('/auth/whatever') you'd need to do window.location.pathname = '/auth/whatever' or window.open('/auth/whatever')

Login by facebook in angular app with loopback backend

I'm making an angular application with strongloop loopback backend.
Also I integrating a third party login by facebook using loopback-passport module.
everything was fine in loopback-example-passport and everything is fine in my app right before the moment of redirecting to my app. User and Access-token created.
the code:
app.get('/auth/login', ensureLoggedIn('/#login'), function(req, res, next) {
console.log('LOOGED IN!!');
console.log(req.user);
res.redirect('/#auth/login');
});
works fine. But i can't understand. how to give authenticated state to my angular application.
i tried to make a controller to route '/#auth/login':
.controller('AuthCalbackCtrl', function($scope, $cookies, $location, AppAuth, $http, User, LoopBackAuth) {
//analogue of User.login responce interceptor
LoopBackAuth.currentUserId = $cookies['userId'] || null;
LoopBackAuth.accessTokenId = $cookies['access-token'] || '';
LoopBackAuth.rememberMe = false;
LoopBackAuth.save();
//asking for currentUser
User.getCurrent(function(user) {
console.log('ser.getCurrent ', user);
});
$location.path('/');
})
This code makes a request GET /api/users/2 but receives 401 error.
If I tweak the file /loopback/lob/models/user.js setting permission:
principalType: ACL.ROLE,
// principalId: Role.OWNER,
principalId: Role.EVERYONE,
permission: ACL.ALLOW,
property: "findById"
Then the request GET /api/users/2 receives 200 and everything ok.
I'm a little confused. I can`t understand how to make my angular app authenticate to loopback, although i know access-token and userId
Have anybody any ideas how to do it?
Here is a valid code.
app.get('/auth/login', function(req, res, next) {
//workaround for loopback-password
//without this angular-loopback would make incorrect authorization header
res.cookie('access-token', req.signedCookies['access-token']);
res.cookie('userId', req.user.id);
res.redirect('/#auth/login');
});
The problem is that loopback-passport signs cookie:
res.cookie('access-token', info.accessToken.id, { signed: true,
maxAge: info.accessToken.ttl });
In string it looks something like the following "s:.eBvo8bpo9Q9wnNrPjjlG%2FAcYqWkxEgNFqn%2FO54rdGwY"
But loopback-angular just copies the access-token to header.authorization, so we need to put there plain cookie.

Resources