Hi Guys I'm learning node.js with expressjs framework. Now I want create a simple site with two page(login page and logged page). With this exercise my main goal is to authorized only the logged user to see the logged page.
I want prevent that a user not registered can see the logged page using www.mysite.com/logged
So in app.js I have added this
app.get('/logged', routes.logged);
Then in index.js(that it's located in ./routes folder) I have wrote this
exports.logged = function(req, res) {
if(req.session.isLogged) {
res.status(200);
res.render('logged', {Title: req.session.name});
} else {
res.status(403);
res.render('403');
}
}
But when I try to access to the logged page via www.example.com/logged I always get 500 Error Internal server error
The error that I receive is this:
Express
500 Error: Failed to lookup view "TypeError: Cannot read property 'commonUserId' of undefined" in views directory "C:\Users\Fabio\Desktop\SitoStatistica\views"
at Function.app.render (C:\Users\Fabio\Desktop\SitoStatistica\node_modules\express\lib\application.js:493:17)
at ServerResponse.res.render (C:\Users\Fabio\Desktop\SitoStatistica\node_modules\express\lib\response.js:798:7)
at Object.handle (C:\Users\Fabio\Desktop\SitoStatistica\app.js:32:6)
at next (C:\Users\Fabio\Desktop\SitoStatistica\node_modules\express\node_modules\connect\lib\proto.js:188:17)
at next (C:\Users\Fabio\Desktop\SitoStatistica\node_modules\express\node_modules\connect\lib\proto.js:190:11)
at next (C:\Users\Fabio\Desktop\SitoStatistica\node_modules\express\node_modules\connect\lib\proto.js:190:11)
at pass (C:\Users\Fabio\Desktop\SitoStatistica\node_modules\express\lib\router\index.js:110:24)
at nextRoute (C:\Users\Fabio\Desktop\SitoStatistica\node_modules\express\lib\router\index.js:100:7)
at callbacks (C:\Users\Fabio\Desktop\SitoStatistica\node_modules\express\lib\router\index.js:167:11)
at callbacks (C:\Users\Fabio\Desktop\SitoStatistica\node_modules\express\lib\router\index.js:170:9)
#pero
Implementing your own authentication system is not a good ideal.
For NodeJS authentication, you should take a look at PassportJS
Authentication then turn out to be very simple:
app.post('/login', passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' }));
then
app.get('/logged', function (req, res, next) {
if (req.isAuthenticated()) {
return res.redirect('/login');
}
return res.render('login');
});
Related
I have created a route to 404.html page if user enters incorrect url route
app.use(function (req, res, next) {
res.status(404).sendFile('public/404.html', {root: __dirname})
})
The problem is that when I enter existing route (in this case I use oauth google authentication) it still leads me to 404 page I created but It should redirect me to google login page.
app.get('/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
Same with logout, it leads me to 404 page
app.get('/logout', (req, res) => {
console.log(`\n`);
console.log('\x1b[1m\x1b[31m', `*** User ${req.user.displayName} has logged out ***`);
req.session = null;
req.logout();
res.redirect('/');
});
Your 404 route needs to be the last route you declare. The declaration order matters. This way, the 404 route handler executes ONLY when no other route has already handled the request (which is what you want it to do).
In Express, routes attempt to match the incoming request in the order the route handlers are registered. Since your 404 handler matches all routes, it has to be last so that it comes into play only when no other route handler has already taken the request.
This is what I always use:
// Pages
app.get('/file', function(req, res){
res.sendFile('/path/to/file.html');
});
// 404
app.get('*', function(req, res){
res.sendFile('/path/to/404/file.html');
res.statusCode = 404;
});
Make sure the 404 handler is after all existing responses, and make sure you restart your server after updating.
I am building an application using node.js and express.js with passport authentication using MVC Architecture. I have strictly followed a tutorial on how to implement and integrate passport authentication using a local strategy. It seems like the strategy is working fine. In my controller which is handling the authentication (using passport.authenticate), successRedirect is always executed given that I submit matching details with an instance in the database. However, after redirecting to wherever successRedirect points to, I am getting a GET request Error 500. Afterwards, if I try to access other routes, I still get the same error, thus failing to display the desired view template. However, if I try to access the same routes without attempting to login, the GET request executes successfully with statusCode 200.
The exact error I get is :
GET /dashboard 500 4.313 ms - 941
users.js route
var usersController = require('../../controllers/usersController');
/* POST login */
router.post('/login', usersController.loginAccount);
usersController.js
module.exports.loginAccount = function (req, res, next) {
passport.authenticate('local', {
successRedirect: 'dashboard',
failureRedirect: '/users/login',
failureFlash: true
}) (req, res, next);
}
index.js route
router.get('/dashboard', ensureAuthenticated, indexController.dashboardPage);
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated())
return next();
else{
req.flash('error_msg', 'Please log in to view this resource');
res.redirect('/users/login');
}
}
Command line after attempting login:
Executing (default): SELECT id, firstname, lastname, email, username, password, address, createdAt, updatedAt FROM clients AS client WHERE client.username = 'nikolaisennn' LIMIT 1;
Serializing user
POST /users/login 302 144.266 ms - 74
Deserializing user
User ID: 65
GET /dashboard 500 4.313 ms - 941
I have been stuck on this issue for a while, tried to find solutions online but I haven't really managed to find what I need. I am sure that there is something small that I am missing, yet I have no clue what it is.
I'm creating a simple PWA to draw in multiple data sources into one application. I'm currently trying to set up authentication using a combination of passport and the twitter-strategy.
After the user has successfully authenticated they're account, twitter redirects to the callback endpoint, with the valid user data.... essentially the auth has been successful. However, when sending the user back to the client side application a html document with the word null is presented, rather than the application.
With the following code, I expect:
Twitter to return to callback URL
Server to perform actions in authSuccess function
Redirect to the provided url on the client
routes.js to server the application shell via the catch all route
Client application to boot and handle the URL served
Currently, only the first two steps are successful, and the app simply displays null (with the correct url in the address bar), rather than the expected output. Changing the location of the writeHead() call to / works, and the user is authenticated as expected ().
routes.js
let users = require('../controllers/userController');
app.get('/user/auth/twitter/callback',
passport.authenticate('twitter', {
failWithError: true
}),
function(req, res) {
console.log('[Twitter] Auth success route hit');
users.authSuccess(req, res);
},
function(err, req, res, next) {
console.log('[Twitter] Auth failure route hit');
users.authFailure(err, req, res, next);
}
);
app.get('*', function(req, res){
console.log('[Route] Catch All: ' + req.path);
res.sendFile(path.resolve(__dirname, '../../public/index.html'));
});
userController.js
authSuccess(req, res) {
console.log('[User Controller] User',req.user);
// Set some cookies here
res.writeHead(302, {'Location': '/user/profile'});
// res.redirect('/user/profile');
res.end();
}
Any help much appreciated. If you need more code, just ask :)
Thanks
I am using PassportJS, and signup and login functions are working quite smooth.
The only problem I am facing with PassportJS (I am using sessions too), that even when the user had logged in, they can again go back to the signup/login url and do signup and/or login back!
This is tempting me. If anyone has a fix/suggestion, please put it down.
UPDATE - 1
Glimpse of myroutes.js: (Using PassportJS along with connet-ensure-login.
app.get('*', function(req, res, next) {
if (req.url.indexOf('/users/login') < 0 &&
req.url.indexOf('/users/signup') < 0) {
req.session.returnTo = null;
}
next();
});
// =====================================
// HOME PAGE (with login links) ========
// =====================================
app.get('/', sabSettings, function(req, res) {
Setting.findOne(function(err, setting) {
if (err)
throw err;
// console.log(setting);
res.render('index', { title: 'eduBird | Reach the glory', setting: req.setting }); // load the index file
});
});
// =====================================
// LOGIN ===============================
// =====================================
// show the login form
app.get('/login', sabSettings, function(req, res) {
// render the page and pass in any flash data if it exists
res.render('login', {
message: req.flash('loginMessage'),
errors: req.flash('error'),
title: 'Login | eduBird',
setting: req.setting
});
});
// process the login form
app.post('/login', passport.authenticate('local-login', {
successReturnToOrRedirect: '/loggedin',
failureRedirect: '/login',
failureFlash: true
}));
// =====================================
// SIGNUP ==============================
// =====================================
// show the signup form
app.get('/signup', sabSettings, function(req, res) {
// render the page and pass in any flash data if it exists
process.nextTick(function() {
res.render('signup', {
message: req.flash('signupMessage'),
errors: req.flash('error'),
title: 'Register | eduBird',
setting: req.setting
});
});
});
// process the signup form
app.post('/signup', passport.authenticate('local-signup', {
successReturnToOrRedirect: '/profile/welcome',
failureRedirect: '/signup',
failureFlash: true
}));
You have not created any sort of access control, but don't worry we will first go through how Passport works and use this to address the problem.
When the user submits a login form, a POST request to our specified path is made resulting in the execution of the passport.authenticate.
The authenticate middleware for that route is configured to handle the local strategy, passport will invoke your implementation of the local strategy.
If an error occurs while interacting with our database, we invoke done(err). Otherwise if the user is not found or the passwords do not match, we invoke done(null, false). If successful we invoke done(null, user).
Calling done will return us to the passport.authenticate and the corresponding redirect will be executed.
At this point, if the sign-in was successful, the user object (from done(null, user)) is attached to the request and you can access the user object through req.user.
The main idea is if the user object is not attached to the request it means the user is not logged in, so we can control our application behaviour for logged in
users with req.user. For example:
// If the user object does not exist it means the user is not logged in
if (!req.user) {
res.render('signin');
} else {
// If the user object exists, the user is logged in and if they try to log in we redirect them to the home page
return res.redirect('/');
}
I hope this helps.
I have a problem with sessions in my app. I'm trying to learn Passport.js based on this tutorial: http://www.sitepoint.com/local-authentication-using-passport-node-js/ . What I want to do is to allow the acccess for only authenticated users. The process of login works great, but when I check if the user is authenticated, it always says not. What could go wrong?
Here is the checking function:
if (req.isAuthenticated()) {
return next();
else {
res.redirect('/');
}
Here is the path from the router:
router.get('/secret', isAuthenticated, function(req, res) {
res.send('Welcome to the secret page');
});
I didn't find any domunentation about how to check if the session was established, where it is and so on.
Try this, taken from passport.js documentation.
app.get('/secret', passport.authenticate('local'), function(req, res) {
// If this function gets called, authentication was successful.
// `req.user` contains the authenticated user.
});
http://passportjs.org/guide/authenticate/