Authentification NodeJS Sequelize Express - mysql

I'm trying implement NodeJS authentification with express, sequelize, and mysql, but i'm blocked. I get login and password values by webservice. I want to match them with database value :
app.get('/login', function (req, res, err) {
var whereUser = {
login: req.query.login,
password: req.query.password
}
if (!req.query.login || !req.query.password) {
res.send('login failed');
//Here my code is wrong !
I try to compare login and password values with database login and passwword values
} else if (req.query.login && req.query.password == UsrPerson.findOne({ where: whereUser })) {
console.log("auth ok")
req.session.user = "amy";
req.session.admin = true;
res.send("login success!");
} else {
console.log("ERROR")
res.send(err)
}
});
How can I do that ? Thank you

app.get('/login', function (req, res, err) {
const { login, password } = req.query;
UsrPerson
.findOne({
where: {
login: login,
password: password
}
})
.then((foundUser) => {
if(!foundUser){
res.send('login failed');
} else {
console.log("auth ok");
req.session.user = "amy";
req.session.admin = true;
res.send("login success!");
}
})
.catch((err) => {
console.log('ERROR');
res.send(err);
});
});
You want to compare if the user with the given username and password combination exists.
And seems like you are storing the password without any encryption, in plain text. This is not secure at all. You have to use a library like bcrypt and only store the encrypted password in your database

The findOne method from sequelize return an instance object of the model.
that means than you can't compare a password to an instance.
The second problem is the findOne method is asynchronous, you need to await it and have an async method.
app.get('/login', async function (req, res, err) {
var whereUser = {
login: req.query.login,
password: req.query.password
}
if (!req.query.login || !req.query.password) {
res.send('login failed');
} else {
// The following code return an instance of the user if it was found.
const user = await UsrPerson.findOne({ where: whereUser }))
// If the user was not found that means the credentials was wrong.
if (user) {
console.log("auth ok")
req.session.user = "amy";
req.session.admin = true;
res.send("login success!");
} else {
console.log("ERROR")
res.send(err)
}
}
});

Related

How i display username after login successful with set cookies using angular nodejs mysql

My login.component.ts file
How to set cookies in the code to display the username.
login Submit(){
console.log(this.userLogin.value)
this.service.LoginData(this.userLogin.value).subscribe((res)=>{
console.log(res)
this.userLogin.reset()
this.successmsg = res.message
this.Username = this.cookieService.set('username', this.Username)
})
}
I am trying to display the username but it only see me undefined.
api service file
LoginData(data:any):Observable<any>{
return this.http.post(`http://localhost:3000/login`,data)
}
dashboard(){
return this.http.get('http://localhost:3000/dashboard')
}
NodeJS file using MySQL database
app.post('/login', (req, res) => {
const username = req.body.username;
const password = req.body.password;
const query = `SELECT * FROM user WHERE username = '${username}' AND password = '${password}'`;
db.query(query, (error, result) => {
if (error) {
console.log('Error querying database:', error);
res.status(500).send('Error querying database');
} else if (result.length === 0) {
console.log('Invalid username or password');
res.status(401).send('Invalid username or password');
} else {
console.log('Login successful');
res.status(200).send({
message: 'Login successful',
username: username
});
}
});
res.cookie('username',`${username}`)
});

User always getting failure redirected using passport?

No matter what I change the user login will keep redirecting to failure instead of success. I don't know if I'm missing something or if I did something wrong. I tried to read the documentation for passport but, I found it pretty confusing. Here is my github link if you need to see the rest of the code. The node files are in app.js and passport-config.js.The sign up part of the website is working. https://github.com/gego144/to-do-list-website/tree/main
const customFields = {
usernameField: 'email',
passwordField: 'password'
}
const verifyCallback = (username, password, done) => {
user_exists = userName_Checker(username), function (err, user) {
if (err) { return done(err); }
if (userName_Checker(username) == false) {
console.log('wrong user');
return done(null, false, { message: 'Incorrect username.' });
}
if (password_finder(username, password)) {
console.log('wrong pass');
return done(null, false, { message: 'Incorrect password.' });
}
console.log('wtf');
return done(null, user);
};
;
}
const strategy = new LocalStrategy(customFields, verifyCallback);
passport.use(strategy);
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
// function that checks to see if the users email is in the database
function userName_Checker(email_name){
var sql = "select * from info where email = ?";
var user_email = [[email_name]];
db.query(sql, [user_email],function (err,result){
if (err) throw err;
var not_unique = result.length;
if(not_unique == 0){
return false;
}
else{
return true;
}
}
)}
// function that checks to see if the password in the database matches with the email
function password_finder(email_name, pass){
var sql = "SELECT password FROM info WHERE email = ?";
var user_email = [[email_name]];
db.query(sql, [user_email],function (err,result){
if (err) throw err;
bcrypt.compare(result, pass, function(err, res){
if(err){ throw err};
if(res){
return true;
}
else{
return false;
}
})
}
)}
My post method in my other file.
app.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect:'/index.html',
failureFlash: true
}))
Edit 1.
I just want to mention that the console.logs you see in verify Callback all don't log anything for some reason too.
The problem might be in the serialization logic.
In passport.serializeUser, you are passing in the whole user object, but when deserializing you are passing the id
Though I am not using SQL, the logic should be similar.
So the code should be something like this:
// Session
// Pass in user id => keep the session data small
passport.serializeUser((id, done) => {
done(null, id);
});
// Deserialize when needed by querying the DB for full user details
passport.deserializeUser(async (id, done) => {
try {
const user = await User_DB.findById(id);
done(null, user);
} catch (err) {
console.error(`Error Deserializing User: ${id}: ${err}`);
}
});
// Export the passport module
module.exports = (passport) => {
passport.use(new LocalStrategy({ usernameField: 'email', }, async (email, password, done) => {
try {
// Lookup the user
const userData = await User_DB.findOne({ email: email, }, {
password: 1, }); // Return the password hash only instead of the whole user object
// If the user does not exist
if (!userData) {
return done(null, false);
}
// Hash the password and compare it to the hash in the database
const passMatch = await bcrypt.compare(password, userData.password);
// If the password hash does not match
if (!passMatch) {
return done(null, false);
}
// Otherwise return the user id
return done(null, userData.id);
} catch (err) {
passLog.error(`Login Error: ${err}`);
}
}));
};
These options for passport seems to malfunction a lot or exhibit weird behaviors, so I suggest you handle the redirection logic like in my controller.
{ successRedirect: '/good',
failureRedirect: '/bad' }
Login controller logic:
(I am omitting the code here for session storage and made some modifications, but this code should work for what you need)
const login = (req, res, next) => {
//Using passport-local
passport.authenticate('local', async (err, user) => {
//If user object does not exist => login failed
if (!user) { return res.redirect('/unauthorized'); }
//If all good, log the dude in
req.logIn(user, (err) => {
if (err) { return res.status(401).json({ msg: 'Login Error', }); }
// Send response to the frontend
return res.redirect('/good');
});
});
})(req, res, next);
};
The actual route:
// Import the controller
const {login} = require('../controllers/auth');
// Use it in the route
router.post('/auth/login', login);

using bcrypt for login in nodejs

I'm having a hard time with integrating bcrypt to try to make my login system safe.
I basically get the username, password the user inputs and try to compare it from the hashed password in my db. here's what I have.
const inputUsername = req.body.inputUsername;
const inputPassword = req.body.inputPassword;
var userLogin = "select * from login where USERNAME = ?"
ibmdb.open(ibmdbconnMaster, function(err, conn) {
if (err) return console.log(err);
conn.query(userLogin, [inputUsername], function(err, rows) {
if (err) {
console.log(err)
}
if (rows.length > 0) {
var pass = ""
for (var i = 0; i < rows.length; i++) {
pass = rows[i]['PASSWORD'];
console.log(pass)
bcrypt.compare(inputPassword, hash, function(err, result) {
if (pass == result) {
console.log("this works")
userAuth = true;
res.redirect('/index')
}
})
}
console.log("does not work")
} else {
userAuth = "false";
res.render('login.ejs')
alert('Incorrect username or password. Please try again')
}
conn.close(function() {
console.log('closed the function /login');
});
})
})
what happens right now is I get the error ReferenceError: hash is not defined
not sure how to fix this. thanks in advance
Where have you defined hash? I don't see it in your code.
Here's an example of auth routes that I've used with bcrypt/node/express:
const Users = require("../users/users-model.js");
router.post("/register", (req, res) => {
// Pull the user's credentials from the body of the request.
const user = req.body;
// Hash the user's password, and set the hashed password as the
// user's password in the request.
const hash = bcrypt.hashSync(user.password, 10);
user.password = hash;
Users.add(user)
.then((newUser) => {
const token = generateToken(newUser);
res
.status(201)
.json({ created_user: newUser, token: token, user_id: newUser.id });
})
.catch((err) => {
res.status(500).json({
message: "There was an error adding a user to the database",
err,
});
});
});
router.post("/login", (req, res) => {
const { username, password } = req.body;
Users.findBy({ username })
.first()
.then((user) => {
if (user && bcrypt.compareSync(password, user.password)) {
const token = generateToken(user);
res
.status(200)
.json({
username: user.username,
first_name: user.first_name,
last_name: user.last_name,
email: user.email,
token: token,
user_id: user.id,
});
} else {
res.status(401).json({ message: "Invalid Credentials" });
}
})
.catch((err) => {
res.status(500).json(err);
});
});
function generateToken(user) {
const payload = {
userid: user.id,
username: user.username,
};
const options = {
expiresIn: "1h",
};
const token = jwt.sign(payload, secrets.jwtSecret, options);
return token;
}
module.exports = router;

Google Authentication using Sails.js

When I have tried to implement Google authentication in my site, using sails JavaScript, and MySQL getting error. I have using passport and passport-Google-auth Strategy. Problem is not getting data to my site from Google
My Express Config(express.js) file is like below,
var passport = require('passport')
, GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
var verifyHandler = function(token, tokenSecret, profile, done) {
process.nextTick(function() {
console.log(profile)
User.findOne({uid: profile.id}, function(err, user) {
if (user) {
return done(null, user);
} else {
var data = {
provider: profile.provider,
uid: profile.id,
name: profile.displayName
};
if (profile.emails && profile.emails[0] && profile.emails[0].value) {
data.email = profile.emails[0].value;
}
if (profile.name && profile.name.givenName) {
data.firstname = profile.name.givenName;
}
if (profile.name && profile.name.familyName) {
data.lastname = profile.name.familyName;
}
User.create(data, function(err, user) {
return done(err, user);
});
}
});
});
};
passport.serializeUser(function(user, done) {
console.log(user)
done(null, user.uid);
});
passport.deserializeUser(function(uid, done) {
User.findOne({uid: uid}, function(err, user) {
done(err, user);
});
});
module.exports.http = {
customMiddleware: function(app) {
passport.use(new GoogleStrategy({
clientID: 'Client Id here',
clientSecret: 'Secret key here',
callbackURL: 'http://localhost:1337/auth/google/callback'
}, verifyHandler));
app.use(passport.initialize());
app.use(passport.session());
}
};
module.exports.cache = {
// The number of seconds to cache files being served from disk
// (only works in production mode)
maxAge: 31557600000
};
module.exports.userlogin = {
userModel: 'user'
};
And My Auth Controller I have added code like below,
google: function(req, res) {
passport.authenticate('google',{
failureRedirect: '/login', scope: ['profile', 'email']
}, function(err, user) {
req.logIn(user, function(err) {
if (err) {
console.log(err);
res.view('500');
return;
}
res.redirect('/');
return;
});
})(req, res);
},
You didn't post your code, so we can't find the exact problem :/
I usually use this method for google/facebook authentication with sails.js.
I follow at first this documentation to add the authentication buttons in the frontend:
https://developers.google.com/identity/sign-in/web/sign-in
Then I post the token that I got from google/facebook to the backend where I can check if the user is banned or whatever... If everything is correct, I create an account for him in the database, I send him his password to his email and finally authenticate him using sessions
(req.session.userId = createdUser.id)
In the next time the user can log in using his email and password or just using google. And both options lead him to the same account :D
My Sails.js function in the authentication controller:
googleAuth: function(req, res) {
if (_.isUndefined(req.param('googleToken'))) {
return res.json({
success: false,
msg: 'Error! Please post your google token'
});
}
var urlToRq = "https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=" + req.param('googleToken');
// Get information about the google user with the specified access token.
request.get({url: urlToRq}, function(err, response, body) {
if(err) {
return res.json({
success: false,
msg: 'Server Error'
});
}
var receivedData = JSON.parse(body);
var userId = receivedData.sub;
var userEmail = receivedData.email;
var emailVerified = receivedData.email_verified;
var userName = receivedData.name;
var userPicture = receivedData.picture;
if (emailVerified == false) {
return res.json({
success: false,
msg: 'Your email is not verified'
});
}
else {
// AUTHENTICATION VERIFIED, YOU CAN SAVE THE CONNECTED USER IN A SESSION, OR ADD HIM TO THE DATABASE AS A NEW ACCOUNT, OR CHECK IF HE HAS A PREVIOUS ACCOUNT OR WHATEVER YOU WANT...
}
});
},
Of course don't forget to run npm install request --save
If anyone needs the facebookAuth function just tell me :D I will post it for you :)

Check user already available in db using sails.js

I am registering a new user by checking it is already available. But for every user it shows "user is already available"
signup: function (req, res) {
var username = req.param("username");
var password = req.param("password");
var status = false;
console.log("user : " + username + " : " + password);
Signup.find({username: username}).exec(function(err, usr){
if (err) {
var response = {status:status, error:"db error"};
res.send(500, response);
} else {
if (usr) {
status = true;
res.send(400, {error: "Username already Taken"});
}
else {
signup.create({username: username, password: password}).exec(function(error, user) {
if (error) {
res.send(500, {error: "DB Error"});
} else {
req.session.user = user;
res.send(user);
}
});
}}
});
},
I assume that in your model it clear that the username must be unique. So use findOne() function. It's return only one record( object ).
signup: function(req, res) {
var username = req.param("username");
var password = req.param("password");
var status = false;
Signup.findOne({ username: username })
.exec(function(err, usr) {
if (err) {
var response = { status: status, error: "db error" };
return res.send(500, response);
}
if (usr) {
//status = true; --> in this case you don't use 'status' so this assignment is unnecessary
return res.send(400, { error: "Username already Taken" });
} else {
Signup.create({ username: username, password: password })
.exec(function(err, user) {
if (err) {
res.send(500, { error: "DB Error" });
} else {
req.session.user = user;
res.send(user.username);
}
});
}
});
}
Signup.find({username: username}).exec(function(err, usr){
// usr is an array
});
the result of find is a list with objects matching your query. The list either has items or no items. In both cases
if (usr) {}
will be true, because you basically just check whether usr is defined which it always is. So change it to
if (usr.length === 0) {
// already exists
}
Or you change find to findOne.