generate random unique token for user id - node.js

I want to generate token as user id and store in database , but how to generate unique one?
should I add timestamp var currentUnixTimestamp = (new Date().getTime() / 1000); as salt? how to do with crypto?
var generateToken = function() {
return new Promise(function (fulfill, reject){
crypto.randomBytes(8, function(error, buf) {
if (error) {
reject(error);
} else {
var token = buf.toString('hex');
fulfill(token);
}
});
});
};

Eight random bytes from a properly seeded crypto library has a low chance of a collision, so you don't usually need to concern yourself with duplicates. In fact, increase that to 16 bytes, and your code is on par with UUID version 4. This is considered a standard for UUIDs. The chances of a collision are so remote it is not usually worth considering.
If you are going that far though, consider using a standard format UUID, such as the node package "uuid". There are also database-side uuid functions which you can add as default to schemas e.g. in Postgres. The advantage is a standardised and well-understood format for your ids, and you won't need to spend any time justifying or maintaining your code for this, just point developers to the standard docs.

If you want this token for authentication purposes you should use json web token instead. It will manage for you and its quite efficient.
Only have to include as a middleware .
app.use(expressJWT({
secret: new Buffer("Your-secret-key").toString('base64')
}).unless({
//# pass api without validating
path: unlessRoutes
}));
You could specify which routes you don't want to to skip in jwt middleware by giving an array in unlessRoutes.
var unlessRoutes = [
'/',
/\/login/,
/\/register/,
/\/customers/,
/\/customer$/,
/\/addCustomer/,
/\/just/,
/\/search/,
/\/dynamic/,
/\/favicon.ico/
]

This is what i think we can do for generating the random token using the crypto:
var passwordResetToken = createRandomToken(data.body.email);
exports.createRandomToken = function (string) {
var seed = crypto.randomBytes(20);
return crypto.createHash('abcde').update(seed + string).digest('hex');
};

Related

Azure keyvault, request for multiple secrets

Im making use of the following node library azure-keyvault to get retrieve stored secrets from azure keyvault. Ive only found the client.getSecret api exposed to retrieve a secret value. Im searching for a way to retrieve multiple secret values in one call. I hav'nt found one yet. Is there a way to do this that i'm missing or its simply not supported.
const { SecretClient } = require('#azure/keyvault-secrets')
const client = new SecretClient(
`https://${KEYVAULT_NAME}.vault.azure.net`,
new DefaultAzureCredential()
)
const [secret1, secret2] = await Promise.all([
client.getSecret(`secret1`),
client.getSecret(`secret2`)
])
Here is the complete code for getting the multiple client secret at once:
var credentials = new KeyVault.KeyVaultCredentials(authenticator);
var client = new KeyVault.KeyVaultClient(credentials);
client.setSecret(vaultUri, 'mysecret', 'my password', options, function (err, secretBundle) {
// List all secrets
var parsedId = KeyVault.parseSecretIdentifier(secretBundle.id);
client.getSecrets(parsedId.vault, parsedId.name, function (err, result) {
if (err) throw err;
var loop = function (nextLink) {
if (nextLink !== null && nextLink !== undefined) {
client.getSecretsNext(nextLink, function (err, res) {
console.log(res);
loop(res.nextLink);
});
}
};
console.log(result);
loop(result.nextLink);
});
});
You can find the complete reference for azure key vault using node js below:
http://azure.github.io/azure-sdk-for-node/azure-keyvault/latest/KeyVaultClient.html#getSecrets
http://azure.github.io/azure-sdk-for-node/azure-keyvault/latest/
Hope it helps.
You can use read-azure-secrets npm package which will return all secrets to you.
E.g.
const secretClient = require('read-azure-secrets');
async function loadKeyVaultValues() {
let applicationID = '';
let applicationSecret = '';
let vaultURL = 'https://<your-key-vault-name>.vault.azure.net/';
let secrets = await secretClient.getSecrets(applicationID, applicationSecret, vaultURL);
secrets.forEach(secret => {
console.log(secret);
});
}
loadKeyVaultValues();
You can try using client.getSecrets(..) method exposed by the REST Api.
Kindly go through the following useful blog, in which all methods have been implemented.
LINK: https://www.red-gate.com/simple-talk/cloud/platform-as-a-service/using-azure-keyvault-with-node-js/
You haven't specified what information about the secret you want to fetch so I am going to assume that you are looking for the secret's value. I am also going to assume you are looking to minimize network traffic for fetching multiple secrets (either for costs or for performance).
Looking at the Azure REST API documentation while there is a route to list multiple secrets it only provides the secret identifier and metadata about the secret (attributes, tags, etc). So if you want to get the secret's value (the actual secret) you will need to make individual calls although get-secrets route can be used to find all the secrets stored in the Key Vault.
As far as the client library, #azure/keyvault-secrets maps pretty closely to the REST API it supports so it will not provide a method that fetches multiple secrets. Even if it did, it would just be a facade over multiple network calls so it would not help reduce the number of network trips.
So to answer your question - it does not look possible today unless all you want is metadata about the secret and not the secret value itself.

Convert NodeJS asynchronous code to Spring Project Reactor

I have below NodeJS code:
// req and resp are http request, response objects
var uri = req.getURI()
var pageView = new PageView(uri)
var token = req.token
if (token) {
UserRepository.findByToken(token, function(notFound, user){
if(notFound) { // means user not found by specified token
var newUser = new User('John Doe')
user.foo = 'some value'
processUser(newUser, pageView)
} else { // user found by token
user.foo = 'some value'
processUser(user, pageView)
}
})
} else { // token does not exist
token = new Token('some value')
resp.setToken(token)
var newUser = new User('John Doe')
user.foo = 'some value'
processUser(newUser, pageView)
}
processUser(user, pageView) {
PageViewRepositiry.save(pageView, function(error, savedPageView){
if(error) {
throw 'error'
}
user.pageViews.push(savedPageView)
// save the modified savedUser
UserRepository.save(user , function(error, savedUser){
})
})
}
It uses Repository pattern as abstraction over database layer (same as the Repository pattern in Spring applications).
Basically it finds user by incoming token (from http req object). If user is found then updates user entity and adds the saved pageView entity and saves the modified user. If user is not found by token then it creates a new User, updates the user with saved pageView, saves the user.
How the same code will be written in Spring Project Reactor (Flux) ?
Is it possible to solve this problem without using block()? Ideally I would like a solution that does not use block().
First of all, you have some logic to generate a token if a token isn't present. For example:
private Mono<String> getToken(String token) {
return Mono
.just(token)
.switchIfEmpty(Mono.just("some token"));
}
In this case, it's a bit overkill to use switchIfEmpty for this, but I assume your process to generate a token is a bit more complex, otherwise you could have worked with Optional<String> in stead (eg. token.orElse("some token")).
Additionally, we also have some logic to either find the user by its token, or create a new user if there is no user by the given token:
private Mono<User> findUserByToken(String token) {
return userRepository
.findByToken(token)
.switchIfEmpty(userRepository.save(new User("John Doe", token)));
}
Now that we have these methods, we can create a PageView and use these methods along the way. The reason I start with creating a PageView is because that's the first "constant" in the entire token, regardless of whether there is a token/user found:
return Mono
.just(new PageView(uri))
.flatMap(pageViewRepository::save)
.flatMap(pageView -> getToken(token)
.flatMap(this::findUserByToken)
.doOnNext(user -> user.setFoo("foo"))
.doOnNext(user -> user.getPageView().add(pageView)))
.flatMap(userRepository::save)
.map(User::getToken);
Now, since you need the token to add to the response, and I figured out that the token is part of the User object somehow (otherwise UserRepository.findByToken() wouldn't work?), it would be easier to just use User::getToken at the end to retrieve the token to pass to the response.
Be aware though, the repository pattern does work properly with Spring, but there is only reactive support for MongoDB, Cassandra, Couchbase and Redis. Other than that there's also reactive support for PostgreSQL through rdbc, but I don't think Spring data has support for that.

How do I generate a session ID in Node.js?

Im trying to learn Node.js without using any third party modules or frameworks. I'm getting to the point where I got to figure out how to give session ids to users who login...
So far I know I can set the session id by writing it in the headers, setting the cookies:
writeHead(200, {'set-cookie':'Math.random() ' } );
and then I can retrieve the session id and later compare it to the database.
request.headers.cookie(request.url);
But how do I GENERATE the session ID value? I am new to programming. The first thing I thought of was using Javascript's Math.random(); and using that value to set the cookie ( session id ). In my mind it feels stupid but that is how far I can think.
How am I suppose to generate the session id using Node.js, no third party modules, barebones please!
Note: You should probably use a session manager for whatever framework you go with.. be it connect, express, koa or any number of others.
This will give you a UUID version 4 (random) using crypto.randomBytes.
var crypto = require('crypto');
module.exports = genUuid;
function genUuid(callback) {
if (typeof(callback) !== 'function') {
return uuidFromBytes(crypto.randomBytes(16));
}
crypto.randomBytes(16, function(err, rnd) {
if (err) return callback(err);
callback(null, uuidFromBytes(rnd));
});
}
function uuidFromBytes(rnd) {
rnd[6] = (rnd[6] & 0x0f) | 0x40;
rnd[8] = (rnd[8] & 0x3f) | 0x80;
rnd = rnd.toString('hex').match(/(.{8})(.{4})(.{4})(.{4})(.{12})/);
rnd.shift();
return rnd.join('-');
}
You could also use the UUID module from npm. The crypto package is not an in-browser option, though you could use Browserify's crypto shim.

Redis: How to save (and read) Key-Value pairs at once by namespace/rule?

I want to utilize Redis for saving and reading a dynamic list of users.
Essentially, Redis is Key-Value pair storage. How can I read all the saved users at once? (for example, creating a namespace "users/user_id")
And since I am a Redis beginner,
Do you think the use of Redis in the above case is proper/efficient?
Thanks.
When using key/values for storing objects you should create a domain specific key by combining the domain name plus the unique id. For example, a user object that might look like this:
// typical user data model
var User = function(params) {
if (!params) params = {};
this.id = params.id;
this.username = params.username;
this.email = params.email;
// other stuff...
};
Then domain key could be created like this:
var createUserDomainKey = function(id) {
return 'User:' + id;
};
If the id was 'e9f6671440e111e49f14-77817cb77f36' the key would be this:
User:e9f6671440e111e49f14-77817cb77f36
Since redis will store string values, you need to serialize, probably with json so to save the user object. Assuming a valid use object would would do something like this:
var client = redis.createClient(),
key = createUserDomainKey( user.id ),
json = JSON.stringify( user ) ;
client.set( key, json, function(err, result) {
if (err) throw err; // do something here...
// result is 'OK'
});
For simple fire-hose queries returning all users, you can do this:
var client = redis.createClient();
client.keys( createUserDomainKey( '*' ), function(err, keys) {
if (err) throw err; // do something here
// keys contains all the keys matching 'User:*'
});
Note that the redis folks discourage the use of 'keys' for production, so a better approach is to build your own index using sorted-set, but if your user list is limited to a few hundred, there is no problem.
And since it returns a list of keys, you need to loop through and get each user then parse the json string to recover the real object. Assuming a populated list of keys, you could do something like this:
var client = redis.getClient(),
users = [];
var loopCallback = function(err, value) {
if (!err && value) {
// parse and add the user model to the list
users.push( JSON.parse( value ) );
}
// pull the next key, if available
var key = keys.pop();
if (key) {
client.get( key, loopCallback );
} else {
// list is complete so return users, probably through a callback;
}
}
// start the loop
loopCallback();
This is a good general purpose solution, but there are others that use sorted sets that are move efficient when you want access to the entire list with each access. This solution gives you the ability to get a single user object when you know the ID.
I hope this helps.
ps: a full implementation with unit tests of this can be found in the AbstractBaseDao module of this project.

SALT and HASH password in nodejs w/ crypto

I am trying to figure out how to salt and hash a password in nodejs using the crypto module. I am able to create the hashed password doing this:
UserSchema.pre('save', function(next) {
var user = this;
var salt = crypto.randomBytes(128).toString('base64');
crypto.pbkdf2(user.password, salt, 10000, 512, function(err, derivedKey) {
user.password = derivedKey;
next();
});
});
However I am confused about how to later validate the password.
UserSchema.methods.validPassword = function(password) {
// need to salt and hash this password I think to compare
// how to I get the salt?
}
In whatever persistence mechanism (database) you're using, you would store the resulting hash alongside the salt and number of iterations, both of which would be plaintext. If each password uses different salt (which you should do), you must also save that information.
You would then compare the new plain text password, hash that using the same salt (and iterations), then compare the byte sequence with the stored one.
To generate the password (pseudo)
function hashPassword(password) {
var salt = crypto.randomBytes(128).toString('base64');
var iterations = 10000;
var hash = pbkdf2(password, salt, iterations);
return {
salt: salt,
hash: hash,
iterations: iterations
};
}
To validate password (pseudo)
function isPasswordCorrect(savedHash, savedSalt, savedIterations, passwordAttempt) {
return savedHash == pbkdf2(passwordAttempt, savedSalt, savedIterations);
}
Based on the nodejs documentation (http://nodejs.org/api/crypto.html), it doesn't look like there is a specific method that will validate a password for you. To validate it manually, you will need to compute the hash of the currently provided password and compare it to the stored one for equality. Basically, you will do the same thing with the challenge password that you did with the original, but use the salt stored in the database instead of generating a new one, and then compare the two hashes.
If you aren't too committed to using the built in crypto library, I might recommend using bcrypt instead. The two are about equal on the security front, but I think bcrypt has a more user-friendly interface. An example of how to use it (taken directly from the bcrypt docs on the page linked above) would be this:
Create a hash:
var bcrypt = require('bcrypt');
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync("B4c0/\/", salt);
// Store hash in your password DB.
To check a password:
// Load hash from your password DB.
bcrypt.compareSync("B4c0/\/", hash); // true
bcrypt.compareSync("not_bacon", hash); // false
Edit to add:
Another advantage of bcrypt is that the output of the genSalt function contains both the hash and the salt in one string. This means that you can store just the single item in your database, instead of two. There is also a method provided that will generate a salt at the same time that the hashing occurs, so you don't have to worry about managing the salt at all.
Edit to update:
In response to the comment from Peter Lyons: you're 100% correct. I had assumed that the bcrypt module that I had recommended was a javascript implementation, and therefor using it asynchronously wouldn't really speed things up on node's single threaded model. It turns out that this is not the case; the bcrypt module uses native c++ code for it's computations and will run faster asynchronously. Peter Lyons is right, you should use the asynchronous version of the method first and only pick the synchronous one when necessary. The asynchronous method might be as slow as the synchronous one, but the synchronous one will always be slow.
Either store password and salt in separate columns in your database, or (my preferred method), store your passwords in your database in a format that's compatible with RFC 2307 section 5.3. An example would be {X-PBKDF2}base64salt:base64digest. You could also store your iteration count in there, which allows you to increase the iteration count in the future for new accounts and accounts that update your passwords, without breaking logins for everyone else.
An example hash from my own PBKDF2 module for Perl looks like
{X-PBKDF2}HMACSHA1:AAAD6A:8ODUPA==:1HSdSVVwlWSZhbPGO7GIZ4iUbrk= which includes the specific hash algorithm used, as well as the number of iterations, the salt, and the resulting key.
This is a modified version of #Matthews answer, using TypeScript
import * as crypto from "crypto";
const PASSWORD_LENGTH = 256;
const SALT_LENGTH = 64;
const ITERATIONS = 10000;
const DIGEST = "sha256";
const BYTE_TO_STRING_ENCODING = "hex"; // this could be base64, for instance
/**
* The information about the password that is stored in the database
*/
interface PersistedPassword {
salt: string;
hash: string;
iterations: number;
}
/**
* Generates a PersistedPassword given the password provided by the user.
* This should be called when creating a user or redefining the password
*/
export function generateHashPassword(
password: string
): Promise<PersistedPassword> {
return new Promise<PersistedPassword>((accept, reject) => {
const salt = crypto
.randomBytes(SALT_LENGTH)
.toString(BYTE_TO_STRING_ENCODING);
crypto.pbkdf2(
password,
salt,
ITERATIONS,
PASSWORD_LENGTH,
DIGEST,
(error, hash) => {
if (error) {
return reject(error);
}
accept({
salt,
hash: hash.toString(BYTE_TO_STRING_ENCODING),
iterations: ITERATIONS,
});
}
);
});
}
/**
* Verifies the attempted password against the password information saved in
* the database. This should be called when
* the user tries to log in.
*/
export function verifyPassword(
persistedPassword: PersistedPassword,
passwordAttempt: string
): Promise<boolean> {
return new Promise<boolean>((accept, reject) => {
crypto.pbkdf2(
passwordAttempt,
persistedPassword.salt,
persistedPassword.iterations,
PASSWORD_LENGTH,
DIGEST,
(error, hash) => {
if (error) {
return reject(error);
}
accept(
persistedPassword.hash === hash.toString(BYTE_TO_STRING_ENCODING)
);
}
);
});
}
Faced with the same question I brought everything together into one module: https://www.npmjs.org/package/password-hash-and-salt
It uses pbkdf2 and stores hash, salt, algorithm, and iterations in a single field. Hope it helps.
There are two major steps involved in this scenario
1) Creating and Storing password
Here you will have to do the following.
Take the user password
Generate a string of random chars (salt)
Combine the salt with the user entered password
Hash the combined string.
Store the hash and the salt in the database.
2) Validating user password
This step would be required to authenticate the user.
The user will enter the username/email and the password.
Fetch the hash and the salt based on the username entered
Combine the salt with the user password
Hash the combination with the same hashing algorithm.
Compare the result.
This tutorial has a detailed explaination on how to do it with nodejs crypto. Exactly what you are looking for.
Salt Hash passwords using NodeJS crypto

Resources