Introduction
In this tutorial, you'll learn how to use Node.js to create a simple web application that demonstrates how to securely handle user credentials. This tutorial is designed for beginners and will teach you fundamental concepts about handling sensitive data in web applications, similar to the security issues that affected the element-data package mentioned in recent news.
Understanding how to properly manage user credentials is crucial for any web developer. This tutorial will show you how to set up a basic Node.js application with Express, create a simple login form, and implement basic security measures to protect user data.
Prerequisites
Before starting this tutorial, you'll need:
- A computer with internet access
- Basic knowledge of HTML and JavaScript
- Node.js installed on your computer (you can download it from nodejs.org)
- A code editor (like Visual Studio Code)
Step-by-Step Instructions
1. Set up your project directory
First, create a new folder for your project and navigate to it in your terminal. This will be the root of your application.
mkdir secure-login-app
cd secure-login-app
Why: Creating a dedicated project folder helps organize your files and makes it easier to manage dependencies.
2. Initialize your Node.js project
Run the following command to create a package.json file, which will track your project dependencies:
npm init -y
Why: The package.json file is essential for managing your project's dependencies and metadata. The -y flag automatically accepts all default settings.
3. Install required dependencies
You'll need Express for the web server and bcrypt for securely hashing passwords:
npm install express bcrypt
Why: Express is a popular web framework for Node.js that makes building web applications easier. Bcrypt is a library that securely hashes passwords, which is crucial for protecting user credentials.
4. Create your main application file
Create a file called app.js in your project directory:
touch app.js
Open this file in your code editor and add the following basic setup:
const express = require('express');
const bcrypt = require('bcrypt');
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware to parse JSON and URL-encoded data
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Serve static files from 'public' directory
app.use(express.static('public'));
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Why: This sets up the basic Express application structure. The middleware helps parse incoming request data, and the static file serving allows us to serve HTML, CSS, and JavaScript files.
5. Create the login form HTML
Create a folder called public and inside it, create an index.html file:
mkdir public
cd public
touch index.html
Fill the index.html file with this code:
<!DOCTYPE html>
<html>
<head>
<title>Secure Login</title>
</head>
<body>
<h1>Secure Login Form</h1>
<form id="loginForm" action="/login" method="POST">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">Login</button>
</form>
</body>
</html>
Why: This creates a basic login form that users can interact with. Notice we're using type="password" for the password field to hide the input.
6. Add the login route
Go back to your app.js file and add the following code to handle login requests:
// In-memory storage for users (in real apps, use a database)
const users = [];
// Login route
app.post('/login', async (req, res) => {
const { username, password } = req.body;
// Find user in our storage
const user = users.find(u => u.username === username);
if (!user) {
return res.status(401).send('Invalid username or password');
}
// Compare password with stored hash
const isMatch = await bcrypt.compare(password, user.password);
if (isMatch) {
res.send('Login successful!');
} else {
res.status(401).send('Invalid username or password');
}
});
Why: This route handles login requests, checks if the user exists, and securely compares the provided password with the stored hash using bcrypt.
7. Add user registration functionality
Add this code to your app.js to allow users to register:
// Registration route
app.post('/register', async (req, res) => {
const { username, password } = req.body;
// Check if user already exists
if (users.find(u => u.username === username)) {
return res.status(400).send('Username already exists');
}
// Hash the password before storing
const hashedPassword = await bcrypt.hash(password, 10);
// Store user (in real apps, save to database)
users.push({
username,
password: hashedPassword
});
res.send('User registered successfully');
});
Why: This registration route securely hashes passwords before storing them, which is a critical security measure. Never store plain text passwords!
8. Test your application
Start your server by running:
node app.js
Open your web browser and navigate to http://localhost:3000. You should see your login form.
Try registering a new user using the registration form, and then log in with those credentials.
Why: Testing your application helps verify that everything is working correctly and gives you hands-on experience with the security concepts.
Summary
In this tutorial, you've learned how to create a basic web application that securely handles user credentials. You've seen how to:
- Set up a Node.js project with Express
- Create HTML forms for user interaction
- Use bcrypt to securely hash passwords
- Implement basic login and registration functionality
This demonstrates the importance of proper credential handling, similar to what went wrong with the element-data package. Remember that in real applications, you should always use a proper database for user storage and implement additional security measures like HTTPS, CSRF protection, and proper session management.



