Can't manage redirect with node.js - javascript

I have a new error with the code below. What I'm trying to do is to build a simple login system, but I have a problem with redirecting res.redirect('/example').
When I try to redirect users the console.log says that Headers have been already sent. I know that there are other questions similar to this but I'm not able to solve this problem. Please help
The file below is the main controller:
exports.login = function(req, res){
var email = req.body.email,
password = req.body.password;
User.findOne({email: email, password: password}, function(err,obj) {
if(obj){
console.log(obj);
console.log('Access approved');
req.session.regenerate(function(){
console.log('New session printed to Sessions DB');
req.session.email = email;
res.redirect('/sec');
});
} else if(!email || !password){
console.log('Please insert data');
}else if(err){
console.log('Error');
req.session.regenerate( function(){
req.session.msg = err;
res.redirect('/login');
});
} else {
console.log('errore not authenticated user');
req.session.msg = err;
res.redirect('/login');
}
});
};
This is the Routes file:
app.post('/logUser', users.login)
And the node:
app.use('/login', function(req, res) {
res.sendFile('public/login.html', {root: __dirname });
});

Ok, finally I found the solution and it's pretty simple.
I need to add next(); to node file, like this:
app.use('/login', function(req, res, next) {
res.sendFile('public/login.html', {root: __dirname });
next();
});
Probably it happen because setting next I can change headers that have been already sent and finally I can reset it again with res.redirect

Related

How to add a session in Node js

we're working on a project for our Programming-Course. We're doing a very small social media platform, where you can register, login, create a profile, view events and log out.
So I set the session variable for logging in, but I also want that people who register are instantly logged in and get redirected to the profile-site. So I have to set another session into the registration app.post I guess, but I have absolutly no Idea how to do this (because I'm a bloody beginner)... Can anybody help? This is the code so far:
//------------Sessionvariables---------------//
app.get('/', requiresLogin, function(req, res) {
res.render('home', {
'username': req.session.user.name
});
});
app.post('/sendLogin', function(req, res) {
//in Datenbank gucken
const user = req.body["username"];
const password = req.body["password"];
db.get(`SELECT * FROM users WHERE username='${user}'`, function(err, row) {
if (row != undefined) {
if(password == row.password) {
req.session['user'] = user;
res.redirect('/home');
}else{
res.redirect('/loginerror');
}
}else{
res.redirect('/loginerror');
}
if(err){
console.error(err.message);
}
});
});
app.get('/logout', function(req, res){
req.session.destroy(function (err) {
if (err) return next(err)
req.session = null;
res.redirect('/start-login');
});
});
// Registration
app.post('/registration', function(req, res) {
const { email, password, username, domicile } = req.body;
// validation
db.run(`INSERT INTO users(email,password,username,domicile) VALUES(?, ?, ?, ?)`, [email, password, username, domicile], function(err) {
if (err) {
return console.log(err.message);
}
return res.redirect('/edit_profile');
});
});
I know that I have to write the session into the app.post /registration - Part, but I don't know how to write it. I'm using Node js, Express and sqlite3...
Thank you!!
Why not just do:
// Registration
app.post('/registration', function(req, res) {
const { email, password, username, domicile } = req.body;
// validation
db.run(`INSERT INTO users(email,password,username,domicile) VALUES(?, ?, ?, ?)`, [email, password, username, domicile], function(err) {
if (err) {
return console.log(err.message);
} else {
// Create the session / save any data you want here
req.session.user.name = username;
/* I would actually call somthing like: createSession(req)
dedicated function that nicely creates the session */
// Redirect to home just like you do after successful login
res.redirect('/home'); // Redirect to home since user registered successfully
}
});
});
By the way always treat error before running other code logic i see you are treating errors at the end of code (in the app.post('/sendLogin',...) :
if(err){
console.error(err.message);
}
Write like this:
if(err){
console.error(err.message);
// and res.end() or similar if its in an express route
} else {
// Do safe stuff here
}
the best method i can suggest you is that after registration success set the user details in session and just redirect to your home page

Use condition in express.js server

How I can use condition in my express.js server. If user login I want to change roots and side server rendering my react app. This condition dont work if(!isLoggin) if user login I change it to true, so this should render my index with react. Wher is problem ?
if(typeof(isLoggin)=='undefined'){
var isLoggin = false;
}
//roots
if(!isLoggin){
//index
app.get('/', function(req, res){
res.render("indexNotLogin",{title:''});
})
//funkcje
app.get('/funkcje', function(req, res){
res.render("funkcje",{title:'Funkcje'});
})
//zaloguj
app.get('/zaloguj', function(req, res){
res.render("zaloguj",{title:'Zaloguj siÄ™'});
})
//zaloguj
app.post('/trylogin', function(req, res){
var username = req.body.name;
var password = req.body.password;
connection.query("SELECT * FROM user WHERE username='"+username+"' AND pass='"+password+"'", function(error, rows,fields){
//callback
if(!!error){
console.log('error in query');
}else{
if(rows.length){
res.send('user zalogowany')
isLoggin=true;
}else{
res.send('user nie istnieje')
}
}
})
})
}else{
console.log("to jest true: "+isLoggin);
app.get('/', function(req, res){
res.render("index",{title:'Zaloguj sie'});
})
}
#edit /zaloguj, /funkcje this is my static roots
At first, implement login with session, not a flag.
app.post('/trylogin', function(req, res){
var username = req.body.name;
var password = req.body.password;
connection.query("SELECT * FROM user WHERE username='"+username+"' AND pass='"+password+"'", function(error, rows,fields){
if(!!error){
console.log('error in query');
}else{
if(rows.length){
res.send('user zalogowany')
req.session.user_id = put_user_id_here
}else{
res.send('user nie istnieje')
}
}
})
})
If you want to check if the user is logged in or not in order to restrict an access, it is better to implement your own Express middleware (http://expressjs.com/en/guide/using-middleware.html#middleware.router). With the authentication middleware like below, you don't have to add a condition block which wraps route definitions.
app.use(function(req, res, next) {
if (req.session.user_id) {
next();
} else {
res.status(401).send('Unauthorized')
}
});
Like this ?
function checkAuth(req, res, next) {
console.log('Jakies id: '+req.session.user_id);
if (!req.session.user_id) {
if(req.route.path=='/'){
res.render("indexNotLogin",{title:''});
}else{
res.send('You are not authorized to view this page');
}
} else {
next();
}
}
My root to after success login:
//index
app.get('/', checkAuth, function(req, res){
res.render("index",{title:''});
})

How can i store token value into my local javascript file

Hi am a beginner to Nodejs i have used passportjs token based authentication if the user logins it provides a token for each user i want to perform some operations based for the users who has token values for example if the user want to see the list of registered users they can view it if he has the token value. Now it provides me the token value perfectly in Postman but i don't know how to store it in a variable and call it via FRONT-END. I want do it via Front End(If he clicks the get users button) it should display the list of users.I have done that in POSTMAN it works finely i don't have an idea how to do it via frontend.
My user Code(Login/Logout)
var express = require('express');
var router = express.Router();
var User = require('../models/user');
var passport = require('passport');
var Verify = require('./verify');
/* GET users listing. */
router.route('/')
.get(Verify.verifyOrdinaryUser, function(req, res, next) {
User.find({}, function (err, users) {
if (err) throw err;
res.json(users);
});
});
router.post('/register', function(req, res, next) {
User.register(new User({ username : req.body.username }),req.body.password, function(err, user) {
if (err) {
return res.status(500).json({err: err});
}
user.save(function(err,user) {
passport.authenticate('local')(req, res, function () {
return res.status(200).json({status: 'Registration Successful!'});
});
});
});
});
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json({
err: info
});
}
req.logIn(user, function(err) {
if (err) {
return res.status(500).json({
err: 'Could not log in user'
});
}
var token = Verify.getToken(user);
res.status(200).json({
status: 'Login successful!',
success: true,
token: token
});
});
})(req,res,next);
});
router.get('/logout', function(req, res) {
req.logout();
res.status(200).json({
status: 'Bye!'
});
});
module.exports = router;
Main.js File. In this main.js file i want to send that token in this get method any idea?
$(".get-users-button").click(function() {
$.ajax({
method: "GET",
url: " http://localhost:3000/users"
})
.done(function(msg) {
console.log(msg);
template(msg);
});
});
When you get back a successful response from the POST to your /login endpoint, store the token on client-side (e.g., window.localStorage.setItem('<your-namespace>-user-token', <the token goes here>);)
Then, when user clicks the 'get-users-button', get the token out of storage (e.g., window.localStorage.getItem('<your-namespace>-user-token'); and store it in a variable if you want.
Then, on your request to get users, add your { 'x-access-token': <token variable goes here> } to your request headers.
As per the documentation for Passport:
If authentication succeeds, the next handler will be invoked and the req.user property will be set to the authenticated user.
Now if I'm understanding your question correctly, you want to pass the token value you obtain from:
var token = Verify.getToken(user)
to the view in which your front-end can do something with. You can pass variables to the view using the following middleware:
app.use((req, res, next) => {
res.locals.token = Verify.getToken(req.user)
next()
}
See the documentation for res.locals for more details.
Example usage:
app.js
const express = require('express')
const app = express()
app.set('view engine', 'pug')
app.use((req, res, next) => {
res.locals.text = 'asdf'
res.locals.token = 'abc'
next()
})
app.get('/', (req, res) => {
res.render('index')
})
app.listen(3000, () => {
console.log('listening on 3000')
})
views/index.pug
doctype html
html
head
title= title
body
h1= text
script.
console.log('#{token}')

expressJS + MongoDB - login/register method

I want to have login/register function in my expressJS API.
So now im just inserting password and email into my database, i want this function to first check if user with this email is already in database - if yes, send response that user is logged.
If not, just insert him to database.
Is it possible to handle some errors in here?
I already have it:
exports.login = function(req, res){
var email = req.body.email;
var pwd = req.body.pass;
db.collection('users', function(err, collection) {
collection.insert({login:email, password: pwd}, {safe:true}, function(err, result) {
res.send("OK");
});
});
};\
and dont know what's next.
You can first try to find the user in your database. Assuming email is unique;
exports.login = function(req, res){
var email = req.body.email;
var pwd = req.body.pass;
db.collection('users', function(err, collection) {
if (err) return res.send(500, err);
collection.findOne({login:email}, function(err, user) {
// we found a user so respond back accordingly
if (user) return res.send('user logged in');
collection.insert({login:email, password: pwd}, {safe:true}, function(err, result) {
if (err) return res.send(500, err);
res.send("OK");
});
});
});
};
notice the return's before the res.send calls when handling errors.

How can I log an end user into my single page application, and redirect them to the Single page application?

How can I log an end user into my single page application, and redirect them to the Single page application, using Backbone.js. Express.js and passport.js.
I have passport, mongo.db, express, and backbone all working on my application. However, upon successful login, I want to load up the single page, backbone js, web application. As of right now, I have the login system working fine. But when I go to redirect the user to the application, after successful login, for some reason it just redirects right back to the login page. I have used console log to make sure that there is nothing wrong with the login code on the server side and everything is working fine. The strange thing is that when I open chrome developer tools, and look at the headers and response, I'm getting the correct index page back, but it's not loading in the browser and the Url remains http://localhost:3000/login.
Here is the code that I suspect must somehow be the culprit:
See edit #2
I've tried both res.sendfile(__dirname + '/public/index.html'); and res.render('index', { user: req.user }); in my base ('/') route but neither of them seems to be loading the index.html. Note that public/index.html and the ejs index are essentially the same files. I started off having my entire app load up on the client side but now I'm trying to move the main index.html file over to the server side so that it can be password protected.
Please let me know if there is any questions at all that will help me better explain this problem, or if there is anymore code that you would like to see. I really want to get this thing figured out.
Edit As you can see with this screenshot of my browser, I have nothing more than simple form. When that form is submitted, I do get back the desired page in the response, but it's not loading up in the browser. I'm also getting a failed to load resource error in the console, but it's failing to load /login for some reason - even though I'm trying to load index.
Edit #2 As much as I hate to paste endless blocks of code, I think the only way to resolve this issue is to paste endless blocks of code.
So here is server.js in all it's glory - minus some of the api routes that are irrelevant:
var express = require('express')
, http = require('http')
, passport = require('passport')
, LocalStrategy = require('passport-local').Strategy
, bcrypt = require('bcrypt')
, SALT_WORK_FACTOR = 10
, mongoose = require('mongoose')
, path = require('path');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(3000);
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.engine('ejs', require('ejs-locals'));
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use( express.errorHandler({ dumpExceptions: true, showStack: true }));
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
//Connect to database
var db = mongoose.connect( 'mongodb://localhost/attorneyapp' );
/*
|-------------------------------------------------------------------------------
| Schemas
|-------------------------------------------------------------------------------
*/
var userSchema = mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true},
});
// Bcrypt middleware
userSchema.pre('save', function(next) {
var user = this;
if(!user.isModified('password')) return next();
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if(err) return next(err);
bcrypt.hash(user.password, salt, function(err, hash) {
if(err) return next(err);
user.password = hash;
next();
});
});
});
// Password verification
userSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if(err) return cb(err);
cb(null, isMatch);
});
};
var Client = new mongoose.Schema({
first_name: String,
last_name: String,
status: String,
});
var Case = new mongoose.Schema({
case_name: String,
status: String,
});
/*
|-------------------------------------------------------------------------------
| Models
|-------------------------------------------------------------------------------
*/
var User = mongoose.model( 'User', userSchema );
var ClientModel = mongoose.model( 'Client', Client );
var CaseModel = mongoose.model( 'Case', Case );
// Seed a user
// var user = new User({ username: 'bob', email: 'bob#example.com', password: 'secret' });
// user.save(function(err) {
// if(err) {
// console.log(err);
// } else {
// console.log('user: ' + user.username + " saved.");
// }
// });
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing.
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
// Use the LocalStrategy within Passport.
// Strategies in passport require a `verify` function, which accept
// credentials (in this case, a username and password), and invoke a callback
// with a user object. In the real world, this would query a database;
// however, in this example we are using a baked-in set of users.
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) {
console.log('error: ', err);
return done(err);
}
if (!user) {
console.log('Unknown user ', username);
return done(null, false, { message: 'Unknown user ' + username });
}
user.comparePassword(password, function(err, isMatch) {
if (err){
console.log('error: ', err);
return done(err);
}
if(isMatch) {
console.log('it is a match');
return done(null, user);
} else {
console.log('invalid password');
return done(null, false, { message: 'Invalid password' });
}
});
});
}));
/*
|-------------------------------------------------------------------------------
| User
|-------------------------------------------------------------------------------
*/
// POST /login
// Use passport.authenticate() as route middleware to authenticate the
// request. If authentication fails, the user will be redirected back to the
// login page. Otherwise, the primary route function function will be called,
// which, in this example, will redirect the user to the home page.
//
// curl -v -d "username=bob&password=secret" http://127.0.0.1:3000/login
//
/***** This version has a problem with flash messages
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }),
function(req, res) {
res.redirect('/');
});
*/
// POST /login
// This is an alternative implementation that uses a custom callback to
// acheive the same functionality.
app.get('/', function(req, res){
console.log('base router is being called');
// res.sendfile(__dirname + '/public/index.html');
res.render('index');
});
app.get('/login', function(req, res) {
return res.render('login');
});
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) {
console.log('NOT USER', info.message);
req.session.messages = [info.message];
return res.redirect('/login');
}
req.logIn(user, function(err) {
if (err) { return next(err); }
console.log('YES USER is loged in');
// return res.sendfile(__dirname + '/public/index.html');
return res.redirect('/');
});
})(req, res, next);
});
app.get('/users', function(req, res){
return User.find( function( err, users ) {
if( !err ) {
return res.send( users );
} else {
return console.log( err );
}
});
});
Also, not sure if this is relevant, but here is my directory and file structure.
Try to return empty value. (undefined, actually)
I mean
res.redirect('/');
return;
instead of
return res.redirect('/');
And don't use res.render('index'... and res.sendfile(... in login! It response data from index.html to client on /login page!

Categories