Passport local protect sub-pages if user didn't login - javascript

I follow this tutorial but has trouble 'protecting' my pages if the user did not login. I want to redirect them to login page.
I've tried to do a middleware in app.js
app.use(function(req, res, next){
if(!req.user){
return res.redirect('/login_');
}
next();
}
})
but I got an infinite loop.

It's because your middleware is being set on all the routes, not just your protected routes. You don't want your login route to be protected.
Set your middleware to check for login on a router that groups all your protected routes. Here's a tutorial on how to do it.

Related

It is possible to clear a cookies only on a specified HTTP route on ExpressJS?

It is possible to clear a cookies only on a specified HTTP route on ExpressJS?
the case is i only want to clear some cookies on a very spesific route, because when i do this:
app.get('/', (req, res) => {
res.clearCookie('foo');
res.render('login', {
layout: 'layout/main-layout.ejs',
page_title:'Login',
);
});
its clear those cookies for all the following route directory, for example the cookies on /dashboard route will also be cleared.
You can clear cookies for a specific route by doing below example.
res.clearCookie('foo', { path: '/' })
Above code clear the cookies in the root directory. If you want to remove cookies in another directory (let's take admin) you can change the directory from "/" to "/admin" and the code will clear the cookies in the /admin directory.
You can read about this more at Express Docs
If you found this answer helpful mark this answer as the correct answer.

Express 4 + Angular 2 HTML 5 Routing Concerns

I am making a basic web app with Express 4 and Angular 2. Here, there is nothing specific to Angular 2 besides the fact I am using its HTML 5 router.
Here is the routing work flow of the app:
There are two main server side routing configurations of the app. Both look similar to this:
/* GET home page. */
router.get('/', authenticationHelpers.isAuth, function(req, res, next) {
res.render('index');
});
/* GET login page. */
router.get('/login', authenticationHelpers.isNotAuth, function(req, res, next) {
res.render('login');
});
These manage explicitly, the two cases in which a user routes to / and /login.
However if the user is logged in and is able to visit / to render the index express view, there are HTML5 routes the user can take advantage of. These include urls like the following:
localhost:5000/user
localhost:5000/profile
localhost:5000/profile/settings
The issue
Clearly there is no router.get('/user'), and there shouldn't be, as this is all front-end work done by the Angular 2 router. However, to enable linking that would allow a user to simply type localhost:5000/profile/settings, and have the site route you to the index file (given that you were logged in) and THEN route you (with angular 2's HTML 5 routing) to your own /profile/settingsI had to place this piece of code in my app.js:
app.all("/*", function(req, res, next) {
res.render('index');
});
This gives me a big problem though. If you are not logged in and you are given the link localhost:5000/profile/settings it will render the index view because it only runs the authenticationHelpers.isAuth function on the router.get('/') routing code above. I would also love to be able to throw 404 errors on routes that don't exist in express, or angular.
However in my mind, to enable this functionality express would have to know about all the HTML 5 routing options as well as the express routing options. To me, this breaks the separation of routing concerns because if I changed an HTML 5 angular route, I'd also have to make a change in express (most likely, view the solution below). I'd like all this functionality, but without this information leaking between route handlers however I simply don't see a way around it. If anyone could help me figure out a better way to do this that would be great! If the information sharing or angular routes with express routes is the only way I've developed the most optimized lean solution I could below:
Potential Solution
router.get(['/', '/user/', '/profile/*'], authenticationHelpers.isAuth, function(req, res, next) {
res.render('index');
});
Add this to the end of all routes
app.all("/*", authenticationHelpers.isAuth, function(req, res, next) {
res.render('index');
});
Should solve your problem

Loading an Angular App from the Backend

I want to check if a user is authenticated from the backend BEFORE anything else has loaded in my angular app, so that no source code has loaded. The initial request to be sent to the back end will be to see whether the user is authenticated. If so, the app will be loaded.
Alternatively, I would like to know how I could have my backend check authentication when the page is requested, and send different content depending on whether the user is logged in or not.
How can I best accomplish this?
app.use(function(req, res, next) {
console.log(req);
next();
});
app.all('*', function(req, res, next) {
console.log(req);
res.send('hey');
})
Why don't these work in my node app?
If you're using a render engine like jade. In your jade template that loads you can embed angular and embed the ng-view on said jade template.
So you have the server handle auth using a jade template tk render your open/public page and then authenticate. Once they pass your Auth test redirect the page to the jade template which has the angular on it. jade will then render the page, once the page loads angular gets called and your angular app will take over the page.
Just be careful if you use URIs that overlap on your server routes and your angular template URIs as they will trigger any middleware on those routes during the ajax call.
I give a very helpful tutorial about authentication with token; in general the idea is use a interceptor that check if the user was authenticated, in case that the user was not authenticate redirect to default or login page
You need to authenticate your user and check his authorization somehow. For example, if you use session-based authentication (quite similar to the way PHP does sessions), you might have a /login site that renders the user's login page. With a custom expressjs middleware you can then redirect unauthorized users or reply with a 401 Unauthorized/403 Forbidden.
app.use(require('cookie-parser')());
app.use(require('express-session')());
// ...
app.post('/login', function (req, res, next) {
if (credentialsAreOK(req) {
req.session.authorized = true;
res.redirect('/pageAfterLogin');
} else {
res.send(401);
}
};
var checkAuthorization = function (req, res, next) {
if (req.session && req.session.authorized) {
return next();
} else {
res.redirect('/login');
// or return res.send(401);
}
};
app.get('/protectedSite', checkAuthorization);
// or
app.get('/protectedSite', checkAuthorization, protectedSiteHandler);
You could have your backend check authentication when the page is requested, and send different content depending on whether the user is logged in or not.
The other way is to resolve a service in your route config which checks authentication before the route is resolved. https://docs.angularjs.org/api/ngRoute/provider/$routeProvider

Using react-router and express with authentication via Passport.js - possible?

So I'm working on a project that incorporates React, Express.js+Passport and Webpack. I understand the concept of pushing everything to a 'master' React component via react-router, then letting it hash out what gets displayed for the given route. That would work great here, I think. To be upfront, I am new to React.
My concerns are:
1) Can I/how can I still use Passport to authenticate my routes? If I understand react-router correctly, I'll have one route in my express app.js file, pointing to, say, a React component named <Application/>. However, Passport needs router.get('/myroute', isAuthenticated, callback) to check the session. Is it still possible to do so with react-router?
2) Furthermore, if this is possible, how do I pass values from the route in Express into my views, in React? I know in a typical view, I could use <%= user %> or {{user}} if I passed that from my route. Is that possible here?
Split a view rendering path from API paths. After all you can set the authentication logic into api calls.
//Auth check middleware
function isAuth(req, res, next) {...}
//API routes
app.post("api/users/login", function() {...});
app.post("api/users/logout", function() {...});
app.get("api/purchases", isAuth, function() {...});
//and so on...
//Wild card view render route
app.use(function(req, res) {
var router = Router.create({
onAbort: function(options) {...},
onError: function(error) {...},
routes: //your react routes
location: req.url
});
router.run(function(Handler) {
res.set("Content-Type", "text/html");
res.send(React.renderToString(<Handler/>));
});
});
So you have to solve how you're going to pass server side rendered data in views to a client side (choose your isomorphic data transferring technique).
You can also create views and the redirection logic on a client side only and firstly render react components in an "awaiting" state that will be resolved on a client after a component will be mounted (check auth state via an API call).

Unable to get simple passportjs with mongoose working

I am using passport-local-mongoose and trying to setup a simple working example using the login example in the repository. But I'm running into problems and I get an error message saying "Error: failed to serialize user into session".
I have reproduced the problem in a gist. (To run the gist, you will need to replace the mongodb server IP and database name in the user.js file and do a POST to the /register endpoint with username and password values.)
In it you will see the endpoints '/setval' and '/getval' which set values in the session and retrieves it, showing that session support is working. The endpoint '/authtest' gives an Unauthorized response, even after doing a POST to '/login'. The endpoint '/authdebug' gives more information - the error mentioned above.
Anyone have any ideas on what is going on? I'm running out of things to try.
I think that passport.authenticate should only be used on routes which are actually used for authenticating the user; in your case, that would be the /login route.
For routes for which you want to make sure a user has previously authenticated, like /authtest, you need a middleware which checks if a user is authenticated:
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/login'); // or your login page
}
// and
app.get('/authtest', ensureAuthenticated, function(req, res) {
...
});
An alternative for that middleware would be connect-ensure-login.

Categories