Samuel Martins I am a full-stack developer who loves sharing the knowledge accumulated over the years with people. The different technologies that I have encountered through my journey allows me to relate to beginners and seniors alike. I write about all things tech.

Build a random password generator in Node.js

5 min read 1600

Password Generator Nodejs

As hacking and phishing scams become more advanced, many developers are taking extra precautions to protect their users. One example is implementing a random password generator, which prompts a user to select a completely randomized password when registering on a site or application, reducing the chances of hackers guessing or stealing login credentials.

In this article, we’ll build our own command-line Node.js random password generator. Our program will generate a random password of a specified length and character composition. After the password is generated, it will automatically be copied to your clipboard, meaning it’s ready for use. We’ll also review how to automatically save your generated password to a text file.

This tutorial is very beginner-friendly, so even if you’re brand new to Node.js, you should be able to follow along. We’ll use the Commander.js package, which enables our program to accept the different commands that we’ll type into the command line. You’ll also need clipboardy for automatically copying your password to your clipboard immediately after it is generated.

You can follow along with the full code for this tutorial at the repository. Let’s get started!

Getting started

First, you need to create an empty folder; you can name it whatever you want. Then, open it with VS Code.

Run npm init to create a package.json file. The package name will be the same as the folder name, which is smartpassword for me. Eventually, we’ll create a symbolic link to run our program using a command with this name:

Generate Package Json File

Installing dependencies

Next, we’ll install the required dependencies for our project, Commander.js and clipboardy:

npm i commander clipboardy

From here, simply create the main file, index.js, then head to your package.json file. Under main: index.js, add type:module. Afterward, import Commander.js into your program with the following code:

import { Command } from "commander";

You can take the const program = new Command(); program variable and run some methods on it, including version number, description, options, required commands, etc. When running your program, if you use either the -h or –help option, you’ll see the different options available for your program. Let’s go ahead and add a few options to our application.

We made a custom demo for .
No really. Click here to check it out.

Adding options

Instead of showing you how to run every single option, we’ll run through a few examples so you get the general idea.

Add a length option

First, let’s start with the option to specify the length of the password. For this, you’ll need only the following code:

program.option('-l, --length <number>', 'length of password', '8')

The command above creates a length option. The first part, -l, --length <number> takes care of the name of the option in full, length, the alias, l, and the required variable, number.

The second part, length of password is the description of the option, while the third part, 8, is the default value that will be passed in as the length of the password if you don’t specify one.

When you console log program.opts(), the program will spit out an object with the length property of value 8. If you run the Node.js index command with an option of length <number>, say node index -l 12, it will spit out an object with the length property of value 12. -l is an alias of the –length option, so this is similar to node index –length 12.

Add a save option

To add a save option, you’ll use the same syntax, except save will not take in a value. It is more like a boolean with a default value of false. If you include it in the running command, then the savevalue will be saved as true:

program.option('-s, --save', 'save the password to secrets.txt')

Add numbers and symbols options

Now, we’ll add options to include numbers and symbols in your random password. Keep in mind that these will be boolean values. That being said, the syntax is largely the same, but with one small tweak:

program.option("-nn , --no-numbers", "password to not include numbers")
program.option("-ns , --no-symbols", "password to not include symbols")

Notice that in these two commands, the –no part prefixes the options. The default value for any boolean property is false, but you want your passwords to include these by default except for when specified by the user, right? The –no part reverses the boolean value, flipping it to true.

That covers all the options required for the program. Keep in mind that you’ll require those values when you create the password generation logic. For that, you actually need to destructure that object and the values:

const { length, save, numbers, symbols } = program.opts()

So far, your file should like the following code:

// initializing the project with the different options
program
    .version("1.0.0")
    .description("simple random secure password generator")
    .option("-l , --length <number>", "length of password", "8")
    .option("-s , --save", "save the password to secrets.txt")
    .option("-nn , --no-numbers", "password to not include numbers")
    .option("-ns , --no-symbols", "password to not include symbols")
    .parse();
const { length, save, numbers, symbols } = program.opts();

Password generation logic

With everything laid out nicely, let’s create the function that actually generates the random password. My password creation function, createPassword, will take in length, numbers, and symbols as arguments within the function:

const generatedPassword = createPassword(length, numbers, symbols)

Now, let’s create variables for numbers, symbols, and characters for you to use in the function:

const alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const integers = "0123456789";
const exCharacters = "[email protected]#$%^&*_-=+";
const createPassword = (length, hasNumbers, hasSymbols) => {
    let chars = alpha;
    if (hasNumbers) {
        chars += integers;
    }
    if (hasSymbols) {
        chars += exCharacters;
    }
    return generatePassword(length, chars);
};

If you console.log(generatedPassword), you’ll see that you have a long password with every character, symbol, and number included. You’ll need to create another function that uses the length parameter to slice the password down to the required length with proper randomization. For this, I used the following code snippet:

const generatePassword = (length, chars) => {
    let password = "";
    for (let i = 0; i < length; i++) {
        password += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return password;
};

Now, if you run the code above, you’ll get your desired password with length, randomization, numbers, and characters specified or not.

To copy the generated password into your clipboard, you need only import clipboardy using the command below:

import clipboard from "clipboardy";

After your password has been generated, add the following code:

clipboard.writeSync(generatedPassword);

To save your password to the file, you can create the following function in the same file, like so:

const savePassword = (password) => {
    fs.open(path.join(__dirname, "/", "passwords.txt"), "a", 777, (e, id) => {
        fs.write(id, password + os.EOL, null, "utf-8", () => {
            fs.close(id, () => {
                console.log("Password saved!!");
            });
        });
    });
};

For this snippet to run successfully, you need to import the fs, os, and path modules:

import os from "os";
import * as fs from "fs";
import * as path from "path";
import { dirname } from "path";
import { fileURLToPath } from "url";

The only thing left to do is to create a symbolic link. We need to edit the package.json file yet again. Right under "main":"index.js", add "preferGlobal": true, then add "bin":"/index.js".

In the index.js file, add the following command above your existing code:

#!/usr/bin/env node

You should see that you’re able to launch your project without Node.js. You simply need to type in your project name and the different options that you have available for it. Your final code should look somewhat like the following:

#!/usr/bin/env node
import clipboard from "clipboardy";
import { Command } from "commander";
import os from "os";
import * as fs from "fs";
import * as path from "path";
import { dirname } from "path";
import { fileURLToPath } from "url";
const program = new Command();
const __dirname = dirname(fileURLToPath(import.meta.url));


// initializing the project with the different options
program
    .version("1.0.0")
    .description("simple random secure password generator")
    .option("-l , --length <number>", "length of password", "8")
    .option("-s , --save", "save the password to secrets.txt")
    .option("-nn , --no-numbers", "password to not include numbers")
    .option("-ns , --no-symbols", "password to not include symbols")
    .parse();

// this function creates the password default
const { length, save, numbers, symbols } = program.opts();
const alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const integers = "0123456789";
const exCharacters = "[email protected]#$%^&*_-=+";
const createPassword = (length, hasNumbers, hasSymbols) => {
    let chars = alpha;
    if (hasNumbers) {
        chars += integers;
    }
    if (hasSymbols) {
        chars += exCharacters;
    }
    return generatePassword(length, chars);
};

// this function formats our password to however you need
const generatePassword = (length, chars) => {
    let password = "";
    for (let i = 0; i < length; i++) {
        password += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return password;
};

// this function saves the password if you have used the -save option.
const savePassword = (password) => {
    fs.open(path.join(__dirname, "/", "passwords.txt"), "a", 777, (e, id) => {
        fs.write(id, password + os.EOL, null, "utf-8", () => {
            fs.close(id, () => {
                console.log("Password saved!!");
            });
        });
    });
};


// getitng the generated password.
const generatedPassword = createPassword(length, numbers, symbols);
if (save) {
    savePassword(generatedPassword);
}

//this functions copies your code to your clipborad  ready for use
clipboard.writeSync(generatedPassword);


console.log(generatedPassword);

Conclusion

Just like that, you’ve built your own, secure, random password generator. I hope that this article has been helpful and you’ll try it out for yourself.

Feel free to fork the repository and build on it. I’d suggest adding a feature to save your passwords in a database or even having the program email your passwords. If you have an improvement you think can be useful, feel free to contact me to collaborate, and if you have any questions, please leave a comment.

200’s only Monitor failed and slow network requests in production

Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third party services are successful, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens while a user interacts with your app. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. .
Samuel Martins I am a full-stack developer who loves sharing the knowledge accumulated over the years with people. The different technologies that I have encountered through my journey allows me to relate to beginners and seniors alike. I write about all things tech.

Leave a Reply