Redirect user to previous page after authentication - javascript

I'm using Google auth through Passport in my app and I'm attempting to redirect the user back to the original page they requested after successful sign-in. I think that location.reload() may be the problem, but not sure how to solve it.
routes.js:
router.post('/auth/google/return', passport.authenticate('google'), function(req, res) {
res.redirect(req.session.returnTo);
req.session.returnTo = null;
});
middleware.js:
var isAuth = function(req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
req.session.returnTo = req.url;
return res.redirect('/');
}
};
called on button click:
$.post('/auth/google/return', {code: authResult.code, access_token: authResult.access_token}).done(function(data) {
location.reload();
});

Try:
router.post('/auth/google/return', passport.authenticate('google'), function(req, res) {
var backURL = req.header('Referer') || '/';
res.json({redir: backURL});
});
And:
$.post('/auth/google/return', {code: authResult.code, access_token: authResult.access_token}).done(function(data) {
window.location.href = data.redir;
});

Related

Getting error: Error: Can't set headers after they are sent. after rerendering page

I am trying to build a registration page with nodeJS and firebase.
When the user gets a registration error the page reloads and the error is shown to the user.
Then if the user tries to register, he gets to the desired page but I get:
Error: Can't set headers after they are sent.
After several hours of researching, I think I have understood the problem.
My code is probably already in the Body or Finished state, but some function tried to set a header or statusCode
With this knowledge, I tried to solve this error but I don't get it done.
Here is my user.js(controller) code:
var express = require('express');
var firebase = require('firebase');
var router = express.Router();
var User = require('../models/user');
var errors;
var errorMessage;
/**
sign up
*/
//sign up page route
router.get('/', function (req, res, next) {
console.log(errors);
if (errors) {
//Handle the errors and show them to the user
res.render('signUp', {error: true, errorMessage: errorMessage});
}else {
res.render('signUp', {title: 'Sign up', user: false, login: true});
}
});
// sign up request
router.post('/', function(req, res, next){
console.log(req.body.user.email + ' made a registration request');
console.log('Passwword: ' + req.body.user.password);
var email = req.body.user.email;
var password = req.body.user.password;
//reference to the firebase database
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
if (error) {
console.log(error.code);
console.log(error.message);
errorMessage = error.message;
errors = true;
res.redirect('/');
}
});
//if user is logged in redirect to homepage
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
res.redirect('/users/home');
console.log('User: ' + user.email + ' has logged in');
}
});
});
module.exports = router;
I hope someone can help me.
If you are using version 7+ of node, you can use async/await like I did in the following snippet:
var express = require('express');
var firebase = require('firebase');
var router = express.Router();
var User = require('../models/user');
var errors;
var errorMessage;
async function createUser(email, password) {
return new Promise(resolve => {
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
if (error) {
console.log(error.code);
console.log(error.message);
errorMessage = error.message;
errors = true;
return resolve(true)
}
resolve(false)
});
})
}
async function authChange() {
return new Promise(resolve => {
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log('User: ' + user.email + ' has logged in');
return resolve(true)
}
resolve(false)
});
})
}
// sign up request
router.post('/', async function(req, res, next) {
console.log(req.body.user.email + ' made a registration request');
console.log('Passwword: ' + req.body.user.password);
var email = req.body.user.email;
var password = req.body.user.password;
//reference to the firebase database
let error = await createUser(email, password)
if (error) {
res.redirect('/');
} else {
let logged = await authChange()
if (logged) {
res.redirect('/users/home');
}
}
});
module.exports = router;

Get token decrypted data

I am struggling with how to get my user decrypted data for the current user, basicly everytime a user does login he get a token at the moment.
After i login i can capture a phote and send it to the server, following my code you guys can see that this request needs a token to work.
Basicly i have a problem related to my app.js(starting file) i try to set a app.use that needs a token for all the routes that comes after the register and login, like this:
app.use('/',require('./routes/index'));
app.use(jwtPermission);
router.use('/fotos',fotos);
my jwt permission file:
var jwt = require('jsonwebtoken');
var jwtConfig = require('../config/jwt');
module.exports = function(req, res, next) {
console.log("entered");
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
console.log(req.headers['x-access-token']);
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token,jwtConfig.secret, function (err, decoded) {
if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
}
router index(connection to authentication and fotos files)
var express = require('express');
var router = express.Router();
router.use(function timeLog(req, res, next) {
console.log('Time: ', Date());
console.log('Request Type:', req.method);
console.log('Request URL:', req.originalUrl);
next(); //passa a solicitação para a próxima função de middleware na pilha
});
router.use('/',require('./authentication'))
router.use('/fotos',require('./fotos'));
router.use(function(req,res,next){
return res.status(404).json({Error:"Invalid Url"});
})
module.exports = router;
when i point to /fotos it doesn't enter the jwtPermission as i want, what is wrong?
you can add your token validation middleware before function that handles some route. For example:
router.use('/fotos', jwtAuthentication, require('./fotos'));

Securing a specific route node.js

Hey I'm using basic auth for Node.JS to secure a route. I'm pretty new to Node.JS and don't understand what the next function does in this case. What I'm trying to do is to secure a the route: /admin/
Note: This is a project for learning purposes so the login part is not too serious and won't be used live.
authentication.js
var basicAuth = require('basic-auth');
exports.BasicAuthentication = function(request, response, next) {
function unauthorized(response) {
response.set('WWW-Authenticate', 'Basic realm=Authorization Required');
return response.send(401);
};
var user = basicAuth(request);
if (!user || !user.name || !user.pass) {
return unauthorized(response);
};
if (user.name === 'name' && user.pass === 'pass') {
return next();
} else {
return unauthorized(response);
};
};
and app.js where I imported the module authentication:
app.get('/admin/', authentication.BasicAuthentication, function(req, res){
console.log("hi u need to login");
});
So what I want to do is to route the user further if the authentication goes through.
Thanks in advance!
Try:
app.get('/admin/', authentication.BasicAuthentication);
app.get('/admin/', function(req, res) {});
This function is known as a middleware:
var basicAuth = require('basic-auth');
exports.BasicAuthentication = function(request, response, next) {
function unauthorized(response) {
response.set('WWW-Authenticate', 'Basic realm=Authorization Required');
return response.send(401);
};
var user = basicAuth(request);
if (!user || !user.name || !user.pass) {
return unauthorized(response);
};
if (user.name === 'name' && user.pass === 'pass') {
return next();
} else {
return unauthorized(response);
};
};
middleware is a function that you can define for various purposes:
using middleware
writing a middleware
In a simple way is a function that runs before performing another action, one general purpose is to protect certain routes for unauthorized access.
You can protect private routes calling then authentication.BasicAuthentication before function(req, res) {}
Some example:
app.get('/user-profile/', authentication.BasicAuthentication, function(req, res){
//private info
});
app.get('/foo/', function(req, res){
//public info
});

Why is the current user having no data?

I am trying to retrieve the current user session then send the data to the view but in the view there is nothing showing i event check the database and there is an active session with all the info. I tried logging the user out and started afresh. Here is my code.
Login works well
router.post('/', jsonParser, function (req, res) {
if (!req.body || req.body.length === 0) {
console.log('request body not found');
return res.sendStatus(400);
}
var username = req.body.username;
var password = req.body.password;
Parse.User.logIn(username, password, {
success: function (user) {
res.redirect('/');
console.log(JSON.stringify(user));
},
error: function (user, error) {
}
});
});
Retrieve current user in the index.js
var username;
/* GET home page. */
router.get('/', function (req, res, next) {
var currentUser = Parse.User.current();
if (currentUser){
currentUser.fetch().then(function (fetchedUser) {
this.username = fetchedUser.getUsername();
}, function (error) {
console.log(error.message);
});
}
res.render('index', {title: 'Home', user: this.username});
});
module.exports = router;
When i try to display the username h1=user there is nothing shown.
You can use arrow functions for access to outer context(this):
currentUser.fetch().then(fetchedUser => {
this.username = fetchedUser.getUsername();
}, error => console.error(error));
But, it can't to help you, because you tried to render before user was fetched. You need to wait while fetch finished.
if (currentUser) {
currentUser.fetch().then(function(fetchedUser) {
res.render('index', {title: 'Home', user: fetchedUser.getUsername()});
}).catch(function(err) {
console.error(err);
// may be render something with err.message here
});
} else {
// render without user
res.render('index', {title: 'Home', user: null});
}
Not sure whether you are getting value for this.username
/* GET home page. */
router.get('/', function (req, res, next) {
var currentUser = Parse.User.current();
var that = this;
if (currentUser){
currentUser.fetch().then(function (fetchedUser) {
that.username = fetchedUser.getUsername();
}, function (error) {
console.log(error.message);
});
}
res.render('index', {title: 'Home', user: that.username});
});
module.exports = router;
Store a reference of this and then try to display it using res.render

Setting admin role using connect-roles & Passport.JS

I am currently trying to set up an admin role in order to access a simple admin page using the following documentation provided via : connect-roles
I ave been banging my head against it for a while and am still lost on how to set a role E.G As of right now am pulling a admin value out of the DB and storing it in a global var for the time being but I have no idea how to use that with connect-roles say to only allow access to my admin page for a specific user.
Can anyone clarify or show an example on how to do this/some guidance as I documentation didn't help me to ensure access to a web page only if the user is an admin?
Ave posted some of the code kinda showing what it looks like at the moment.
Code
var admin = 'Admin';
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'test'
});
var passport = require('passport');
var ConnectRoles = require('connect-roles');
var roles = new ConnectRoles();
var passportLocal = require('passport-local');
app.use(passport.initialize());
app.use(passport.session());
app.use(roles.middleware());
passport.use(new passportLocal.Strategy(function (username, password, done) {
connection.query({
sql : 'SELECT * from `userman_users` WHERE `username`= ?AND`password` = sha1(?)',
timeout : 40000, // 40s
values : [username, password]
}, function (error, results, rows) {
if (results.length > 0) {
response = "Success";
} else {
console.log('Error while performing Query.');
response = "Failed";
}
if (response === "Success") {
done(null, {
id : username
});
} else if (response === "Failed") {
done(null, null);
}
});
})
);
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
done(null, {
id : id
});
});
roles.use(function (req, action) {
if (!req.isAuthenticated()) return action === 'access home page';
})
roles.use(function (req) {
if (req.user.role === 'admin') {
return true;
}
});
app.get('/', redirectToIndexIfLoggedIn, function (req, res) {
res.render('login');
});
app.get('/index', checkLoggedIn, function (req, res) {
res.render('index', {
isAuthenticated : req.isAuthenticated(),
user : req.user
});
});
app.get('/admin', user.can('access admin page'), function (req, res) {
res.render('admin');
});
function checkLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
this is an example:
var express = require('express');
...
var passport = require('passport');
var LocalStrategy = require('passport-local');
var ConnectRoles = require('connect-roles');
...
var app = express();
//===============PASSPORT=================
// Passport session setup.
passport.serializeUser(function(user, done) {
console.log("serializing " + user.username);
done(null, user);
});
passport.deserializeUser(function(obj, done) {
console.log("deserializing " + obj);
// simulate an admin user
obj.role = obj.username == 'admin' ? 'admin' : 'user';
done(null, obj);
});
...
//===============CONNECTION RULES=================
var user = new ConnectRoles({
failureHandler: function (req, res, action) {
// optional function to customise code that runs when
// user fails authorisation
var accept = req.headers.accept || '';
res.status(403);
if (~accept.indexOf('html')) {
res.render('access-denied', {action: action});
} else {
res.send('Access Denied - You don\'t have permission to: ' + action);
}
}
});
...
app.use(passport.initialize());
app.use(passport.session());
app.use(user.middleware());
//anonymous users can only access the home page
//returning false stops any more rules from being
//considered
user.use(function (req, action) {
if (!req.isAuthenticated()) return action === 'access home page';
});
//users logged can access to public pages
user.use(function(req, action){
if(req.isAuthenticated() && action != 'access private page' && action != 'access admin page')
return true;
});
//moderator users can access private page, but
//they might not be the only ones so we don't return
//false if the user isn't a moderator
user.use('access private page', function (req) {
console.log('access private page');
if (req.user.role === 'moderator') {
return true;
}
});
//admin users can access all pages
user.use(function (req) {
if (req.user.role === 'admin') {
return true;
}
});
...
/* GET home page. */
app.get('/', user.can('access home page'), function(req, res, next) {
res.render('index', { title: 'Express' });
});
//displays our signup page
app.get('/signin', function(req, res){
res.render('signin');
});
//sends the request through our local signup strategy, and if successful takes user to homepage, otherwise returns then to signin page
app.post('/local-reg', passport.authenticate('local-signup', {
successRedirect: '/',
failureRedirect: '/signin'
})
);
//sends the request through our local login/signin strategy, and if successful takes user to homepage, otherwise returns then to signin page
app.post('/login', passport.authenticate('local-signin', {
successRedirect: '/',
failureRedirect: '/signin'
})
);
// Simple route middleware to ensure user is authenticated.
app.use(function(req, res, next) {
if (req.isAuthenticated()) { return next(); }
req.session.error = 'Please sign in!';
res.redirect('/signin');
});
//logs user out of site, deleting them from the session, and returns to homepage
app.get('/logout', function(req, res){
var name = req.user.username;
console.log("LOGGIN OUT " + req.user.username)
req.logout();
res.redirect('/');
req.session.notice = "You have successfully been logged out " + name + "!";
});
app.get('/private', user.can('access private page'), function (req, res) {
res.render('private');
});
app.get('/admin', user.can('access admin page'), function (req, res) {
res.render('admin');
});
app.use('/users', users);
....
module.exports = app;
With connect-rules you define the rules do you want to use (user.use in this case). If you pass an action as first parameter the strategy is only used if the action passed in the function is equal to it. Then you trigger the rules in the routes with user.can passing the action. In this example I define an extra filter strategy to grant access to users that are logged and request routes that are not marked with admin or moderator privileges e.g
/* GET home page. */
app.get('/', user.can('access home page'), function(req, res, next) {
res.render('index', { title: 'Express' });
});
After the user is logged, we need to have another strategy in case the user isn't admin or moderator.
U can use framework like sailsJS and npm module sails-generate-auth
And after setup, use your own middleware to block routes
//allow admin only localhost:PORT/admin at policies.js
'admin': ['passport', 'sessionAuth', 'isAdmin'],
'*': ['passport', 'sessionAuth'],
//isAdmin policy
module.exports = function(req, res, next) {
// User is allowed, proceed to the next policy,
// or if this is the last policy, the controller
if (req.user.role == 'admin') {
return next();
}
// User is not allowed
return res.forbidden('You are not permitted to perform this action.');
};
Using the following logic I was able to have admin functionality based on value within the DB:
app.get('/admin', function (req, res) {
connection.query({
sql : 'SELECT role from `auth_users` WHERE `username`= ?',
timeout : 40000, // 40s
values : [req.user['id']]
}, function (error, results, rows) {
if (results[0]['role'] === "admin") {
admin = (results[0]['role']);
res.render('admin', {
isAuthenticated : req.isAuthenticated(),
user : req.user
});
} else {
admin = "";
res.redirect('/index');
}
})
});

Categories

Resources