Express.js how to use security on login and afterwards - node.js

I have a web app being built in express.js with a postgresql db.
I was wondering about how to implement the security, but everyone uses something different ( i guess thats a good thing? ).
Different modules different authentication sequences etc.
What I have at the moment:
1) User form post to for example /login
2) app routes to specific route
3) in route I try the following
var localconstring = "postgres://" + usr + ":" + pass + "#ip:port/db";
var client = new pg.Client(localconstring);
client.on('drain', client.end.bind(client));
client.connect(function (err, client, done) {
The database uses md5 so the pass is already protected by the db.
What should really happen?
Should I salt and hash the username and password and then save the salted/hashed credentials alongside the salt and then use the md5 of the db also?
If so which module?
Should I be logging in like that or try to do a select * from pg_roles/users ??
Thanks a lot!
(regarding the salt and hash if possible some detailed examples as I am pretty knew with authentication security)
Forgot to mention. cookies..
After the authentication I set the following cookies:
res.cookie('user', req.body.lguser.username, { signed: true })
res.cookie('watcher', o, { signed: true })
And look em up afterwards
req.signedCookies.user !== undefined
Is the signed attribute secure?

You should generate a key. This key should be saved on a cookie and on the database. Then when the user makes a petition, you can get the key on the cookie and search the user on the database.
There are libraries that help you on this, take a look at Passportjs:
http://passportjs.org/

First of all md5 is NOT seure anymore, so I would recommend you using 'sha512'.
A snippet would be something like this:
var crypto = require('crypto');
var salt = crypto.pseudoRandomBytes(32);
crypto.pbkdf2(userPassword,salt,1024,32,function(err,finalPassword){
//on the db you save the salt as a field and the SALTEDPASSWORD !!
//in this case the finalPassword
}
So when the user logs-in you get the user from the db by username and do the following:
//after getting the user from DB recalculate the hash
crypto.pbkdf2(passw,user.salt,1024,32,function(err,corrPass){
if(corrPass.toString() == user.password.toString()) // log in the user
//where user.password is the result from the db query
}
And I do recommend using passport like the other dude said, it simplifies all of the cookie stuff.
Hope it helped !

Related

How to verify a hashed secret without knowing the salt?

I store the API-Keys as hashes in a database.
...
async function createToken(userId:number) {
...
const salt=await bcrypt.genSalt(15)
const hash=await bcrypt.hash(token, salt)
await db.store({userId,hash})
}
async function verifyToken(token:string){
const userId= //I don't know the UserID since only the token is sent as HTTP header
const hashes= db.get(userId)
for(const hash of hashes) {
if(await bcrypt.compare(token, hash)) {
return true
}
}
return false
}
How do I verify the token validity without knowing the userID?
The only option I see is to loop through all DB records, and try if the produced hash for that record matches. But this results potentially in thousands of hashes checked before I find the right one.
I may reduce this to only the tokens belonging to a specific UserID. However, this would require my users to also send there userID which I don't want them to do.
Seems like you are using bcrypt hashes as token to authenticate the users, but that's not the actual purpose of such hashes. If you need to use a token, why not use something like JWT. It can hold the user information, and can be verified without a single db call.

Trying to get info from database nodejs / sqlite

I'm doing a login prototype for my app, on the backend I'm trying to recieve the info (email and password) from the frontend to compare with the registered info from the database and validate the user login.
This is what I have done
const infos = request.query;
const email = infos.email as string; // email input frontend
const password = infos.password as string; // password input frontend
const checkLogin = await db('usersLoginsDB') // catching equal from database
.where('usersLoginsDB.email', '=', email)
.where('usersLoginsDB.password', '=', password)
.select('usersLoginsDB.email', 'email')
.select('usersLoginsDB.password', 'password')
After this, I have a checkLogin as type any[] with email and password, and I can't do something like checkLogin.email to use this info.
I tried this and kind of worked
let resultEmail = checkLogin.map(a => a.email) as unknown;
let testEmail = resultEmail as string;
But I'm not sure this is right, I would like to know if there is another way to do it, to get this checkLogin.email to work, or to get the email info from the database in a different way other than using .where and .select.
Thanks in advance.
Probably checkout knex or any other query builder. You don’t need to query everything all at once. You can do this in simple steps:
Query dB to check if the user email exists if it doesn’t throw an error.
If user email exists you need to now verify password. Query the DB to verify it.
If all goes well you can sign in the user. For example, if you have JWT setup send the token back to the user.

Node.js and mongoose - prevent salt and password to return to client

I have a node.js app with mongoose. my problem is that when returning entities with populated user, the user data includes secure data like salt, tokens and password. I used the following method to prevent private data from going back to client:
User.methods.toJSON = function() { // Do not change to lambda expression
const SERVER_ONLY_PROPERTIES = ['tokens', 'salt', 'password'];
var user = this.toObject();
SERVER_ONLY_PROPERTIES.forEach(propKey => {delete user[propKey]});
return user;
}
Everything worked great, until I used the lean() function in my code.
when using lean the toJson method isn't being called and the private data returns to client. what are my options?
Instead of taking out the stuff that you don't want to return, you should instead have a process that builds a new object to return that explicitly includes only the necessary pieces of data. That's the best practice as far as security, if I'm not mistaken.

Keeping Session data on backend only using JWT

I'm using JWT on my application and I define my claims like so:
const claims = {
iss: process.env.DOMAIN,
scope: "game",
email: user.get("email")
};
I verify the token like so:
nJwt.verify(socket.handshake.query.token, app.get("jwt.secret"), (err, decoded) => {
if (err) return;
console.log(decoded.body.email); // doge#doge.com
});
However, it forces me to add session data into claims object. Instead, I want to use the token as a session identifier and keep session values on backend only, such as:
nJwt.verify(socket.handshake.query.token, app.get("jwt.secret"), (err, decoded) => {
if (err) return;
// Since we verified token, read token's session data from backend
});
Is there any example about doing this?
Ps. I use Redis so I can SET/GET values via Redis, but I feel like it's bad practice since I'll be developing whole session thing myself.
To uniquely identify your token, you could take the whole tokenstring as identifier, though this doesn't make much sense since its too long and unhandy.
Instead, jwt has already standardized a claim for this purpose: jti.
So generate your token something like this:
var claims = {
iss: process.env.DOMAIN,
jti: yourGenerateUniqueIdFunction();
};
After JWT verification, you have the jti value.
In the Backend you could model your Session K/V Store like this:
[jti].[keyName] -> [value]
Accessing K/V something like this:
Session.get('3452345.email') //doge#doge.com
Another way how to achieve what you want is just enabling the default session mechanism in express (https://github.com/expressjs/session),
then using https://github.com/tj/connect-redis to store the session in your redis store. In this way you could just easily read and write to the req.session and it will be backed to your configured redis store.

Authentication proxy - req.user.sub persistent?

Situation
I used the node.js quickstart project from auth0 to build an authentication-proxy. Reason for this is that I cannot merge my spring backend with the Quickstart spring example.
In order to let the spring backend identify the user, I pass the user's sub as shown below.
var authenticate = jwt({
secret: new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64'),
audience: process.env.AUTH0_CLIENT_ID
});
...
app.get('/secured/*', function (req, res) {
var url = apiUrl + req.url;
var userId = req.user.sub; // 'auth0|muchoCrypto123'
url += "?userId=" + userId;
req.pipe(request(url)).pipe(res);
});
I am currently also investigating the usage of HttpRequestServlet in spring to retrieve user details.
Question
Is req.user.sub a value that I can use to identify the user without worrying that this value might change? So far I couldn't detect changes.
In the user management console I found the following:
user_id auth0|muchoCrypto123
Thus I assume that the user_id won't change. Can anyone confirm?

Resources