In this tutorial we are going to create a One-Time Password (OTP) Authenticator in JavaScript and Node.js. You can use as a simple project for understanding two-factor authentication mechanisms and improving your Node.js skills. Or you can simply use it as viable alternative to Google Authenticator or microsoft Authenticator.
mkdir otp-authenticator
cd otp-authenticator
npm init -y
npm install speakeasy prompt-sync qrcode-terminal
Create a new file named auth.js in your project directory, and open it in your editor.
Add the following lines at the top of auth.js to import the modules you'll use:
const speakeasy = require('speakeasy');
const prompt = require('prompt-sync')({sigint: true});
const fs = require('fs');
const path = require('path');
const qrcode = require('qrcode-terminal');
Below the module imports, add code to handle data storage in a JSON file:
const dataFile = path.join(__dirname, 'data.json');
// Initialize data
let data = {};
if (fs.existsSync(dataFile)) {
data = JSON.parse(fs.readFileSync(dataFile, 'utf8'));
}
The add command will allow users to input a label and a secret key for an account, optionally verifying it with an OTP:
function add() {
const label = prompt('Enter label (e.g., GitHub:usern): ');
const secret = prompt('Enter the secret key provided by the service: ');
const userTOTPInput = prompt('Enter a current OTP from your authenticator app to verify (optional, press enter to skip): ');
let verificationPassed = true;
if (userTOTPInput.trim() !== '') {
verificationPassed = speakeasy.totp.verify({
secret: secret,
encoding: 'base32',
token: userTOTPInput,
window: 1
});
}
if (verificationPassed) {
data[label] = { secret: secret };
fs.writeFileSync(dataFile, JSON.stringify(data, null, 2));
console.log(`${label} account added successfully.`);
} else {
console.log('Verification failed. Please check the OTP entered and try again.');
}
}
The show command will display OTP codes for all or filtered accounts based on keywords:
function show() {
const filters = process.argv.slice(3);
console.log('Filtered OTP Codes:');
Object.keys(data).forEach(label => {
const isMatch = filters.every(filter => label.toLowerCase().includes(filter.toLowerCase()));
if (isMatch || filters.length === 0) {
const secret = data[label].secret;
const token = speakeasy.totp({
secret: secret,
encoding: 'base32'
});
console.log(`${label}: ${token}`);
}
});
}
Add command handling logic to auth.js:
const command = process.argv[2];
switch(command) {
case 'add':
add();
break;
case 'show':
show();
break;
default:
console.log('Invalid command. Use "add" or "show".');
}
To add an account: node auth.js add, then follow the prompts.
To view OTPs: node auth.js show or node auth.js show
Congratulations! You've created a basic OTP authenticator in JavaScript and Node.js. This project covers key concepts like TOTP generation, command-line input/output, and simple data storage. As you become more comfortable, consider adding features
This tutorial will guide you through building a command-line OTP authenticator similar to Google Authenticator, using the speakeasy library for generating TOTP (Time-Based OTP) codes, and prompt-sync for handling user input.
This tutorial will guide you through building a command-line OTP authenticator similar to Google Authenticator, using the speakeasy library for generating TOTP (Time-Based OTP) codes, and prompt-sync for handling user input.
This tutorial will guide you through building a command-line OTP authenticator similar to Google Authenticator, using the speakeasy library for generating TOTP (Time-Based OTP) codes, and prompt-sync for handling user input.
Mastering error handling in ExpressJS: Prevent crashes and enhance stability with effective strategies for managing unhandled rejections and exceptions.