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
Related
I am very new to web development, and have been using Google as a guide.
If I put a wrong login that does not match what I have in my database, the website just gets stuck and keeps trying to “load”. I also am confused on how to do token-based authentication for login and would love some more guidance on that, the guide I am following talks about database encryption and OAuth 2.0 with Google.
If the user logs in with a username and password that is not correct, I just want it to give an error and reload back to login.ejs.
Thank you for any help!
The issue might be you are not returning anything when foundUser is null or if the password doesn’t match.
If there is any error you can redirect it to the /login route with query param (err) which can be read by the client using JS at page load. If there is a nonempty query param err then read it and show it in some popup.
res.redirect("/login?err=The username does not exist");
//connect to mongodb
mongoose.connect("mongodb://localhost:27017/userDB", {
useNewUrlParser: true
});
const userSchema = {
username: String,
password: String
};
const User = new mongoose.model("User", userSchema);
app.get("/", function(req, res) {
res.render("home"); //render home.ejs
});
app.get("/login", function(req, res) {
res.render("login"); //render login.ejs
});
app.post("/login", function(req, res) {
const username = req.body.username;
const password = req.body.password;
try {
User.findOne({
username: username
}, function(err, foundUser) {
if (err || !foundUser) {
return res.redirect("/login?err=The username does not exist");
}
if (foundUser.password !== password) {
// you can use bcryptjs for hashing and comparing hashed values.
return res.redirect("/login?err=The username or password is invalid");
}
res.redirect("/counter");
});
} catch (error) {
res.redirect("/login?err=something went wrong!");
}
});
You can read more about handling authentication in nodeJS here. also check passportjs
This is something,that really confuses. me. Let us suppose you have a REST API where you want the user to logout. After login out,the jwt(json web token) should be destroyed,so the user can not have access to the server's resources(ie menu,dishes etc).
In my case the user can logout,but he/she can still perform all the requests(get dishes,post and delete),until the token is valid. Here is my code.
verify.js
var User = require('../models/user');
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
var config = require('../config.js');
exports.getToken = function (user) {
return jwt.sign(user, config.secretKey, {
expiresIn: 3600
});
};
exports.verifyOrdinaryUser = function (req, res, next) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.secretKey, function (err, decoded) {
if (err) {
var err = new Error('You are not authenticated!');
err.status = 401;
return next(err);
} 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
var err = new Error('No token provided!');
err.status = 403;
return next(err);
}
};
I am invalidating the token after a period of 1 hour.
And users.js where I set all the routes with their tasks. ie localhost:3000/users/login,localhost:3000/users/register and localhost:3000/users/logout. So.
var express = require('express');
var router = express.Router();
var passport = require('passport');
var User = require('../models/user');
var Verify = require('./verify');
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.post('/register', function(req, res) {
User.register(new User({ username : req.body.username }),
req.body.password, function(err, user) {
if (err) {
return res.status(500).json({err: err});
}
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;
It seems that the logout method req.logout,doesn't work:(. Any ideas?
Thanks,
Theo.
You cannot log out a user that has a valid token if all the data is on the client side. You would need to store some state on the server to distinguish between users that you explicitly logged out and those that you didn't and check this state every time. If all of the data is entirely in the JWT token then you can't do anything to make it invalid (other than changing your secret that would invalidate all of the tokens, not just this one).
You actually discovered the main disadvantage of using authentication based entirely on the data that is included in the token itself. Those tokens cannot be invalidated. Once they're out then must be assumed to be active. You could only ask the client to forget it, but the client cannot be trusted to do that.
In theory you might have a fast data store like Redis where you keep all of the valid tokens and remove tokens from there to force logout, and check this storage on every request to know who is still logged in and who is not, but if you do that then you might store the session data in Redis in the first place and give only some random keys to that data store to the clients.
JWT is designed to be stateless. This means that all the information needed is contained in the token itself.
As the token has already been created, logout will have no effect on the validity of this.
This leaves you needing to keep a list of 'invalidated' tokens, which means you have once more introduced state.
If you are only concerned about subsequent users on the same machine, you could delete the token on logout, thus preserving the statelessness, but this will not protect against cases where the token has been captured.
I'm trying to make a simple login but whenever I try to get the hashed password the mongo console throws me this error:
ReferenceError: test is not defined
for some reason every time I insert data it goes into an admin db which I don't create it is there by default:
show dbs
admin 0.000GB
local 0.000GB
this is my connection:
var db = null;
MongoClient.connect("mongodb://localhost:27017/firstApp", function(err, dbconn){
if(!err){
console.log("Connected");
db = dbconn;
}
});
And this is how I try to login (right now is commented because I want to get the hashed password.
app.put('/users/signin', function(req, res, next){
db.collection('users', function(err, usersCollection){
usersCollection.findOne({username: req.body.usern}, function(err, user){
console.log(user.password);
/*bcrypt.compare(req.body.pass, user.password, function(err, result){
if(result) {
return res.send();
} else {
return res.status(400).send();
}
});*/
});
});
});
However when I try that console.log() command, it throws me this:
ReferenceError: user is not defined
PS. I'm learning.
I'm making a simple webapp with facebook login.
If the facebook login button on my page is clicked,
FB.api(
'/me',
'GET',
{"fields":"id,name,birthday,gender"},
function(response) {
$.post('fb_login', response, "json");
}
);
is called, and a router handles '/fb_login' request; in the router the server checks the id of json object is already in its DB. If not, res.render('signup', ...) should be called.
However it didn't work. I already checked that res.render() was called, but the page 'signup.jade' didn't show up.
Here is my source code of router.
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
var pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: '1012'
});
/* GET home page. */
router.post('/', function(req, res, next) {
var userid = req.body.id;
if (userid) {
pool.getConnection(function(err, connection) {
if (err) {
console.error('DB Connection error!!');
return;
}
console.log('DB Connection Success!!');
connection.query('use vasket');
connection.query('select count(*) result from user where userID=?',
[userid], function(err, result, field) {
var isAlreadyUser = result[0].result;
console.log(isAlreadyUser);
if (isAlreadyUser == 1) {
req.session.userid = userid;
res.redirect('/');
res.end();
console.log('DB FB Login Success!!');
connection.release();
}
else {
connection.release();
console.log('FIRST TIME!');
//This method was called, but the page rendered didn't
res.render('signup', {id: req.body.id, name: req.body.name, birthday: req.body.birthday, gender: req.body.gender});
}
});
});
} else {
res.redirect('/');
res.end();
}
How can I fix it?
To help debugging maybe you can modify your code like that :
// ... your code before
else {
connection.release();
console.log('FIRST TIME!');
console.log(req.body);
//This method was called, but the page rendered didn't
res.render(
'signup',
{
id : req.body.id,
name : req.body.name,
birthday: req.body.birthday,
gender : req.body.gender
} ,
function(err, html){
if(err) console.log(err);
console.log(html);
//res.send(html);
// trying same but forcing status
res.status(200).send(html);
}
);
}
});
});
} else {
res.redirect('/');
res.end();
}
This is an older question, but it's still in need of a solid answer. I had the exact same problem, but I think I've figured it out.
If the server's returning the proper response, that's not where your problem lies. jQuery (in the browser) will render the response, but you have to tell it to do so.
Here's what I had that was responding properly but not rendering:
$("#getsome").click(function() {
$.get("/task/create");
});
And here's how I got it to render:
$("#getsome").click(function() {
$.get("/task/create", function( data ) {
document.write(data);
});
});
Note that you may not need to replace the entire DOM like I'm doing.
References:
Replacing the entire
DOM
jQuery.get
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.