Menu
CoddyTech

Signup Rules

Part of the Auth and Security section of Coddy's Node.js journey. Lesson 7 of 24.

Right now anyone can sign up twice with the same name, or with the password 1. Signup has to check what it receives before it stores anything.

Two status codes say what went wrong. 400 Bad Request means the request itself is not acceptable, like a password that is too short. 409 Conflict means it clashes with data you already have, like a name that is taken.

Names also need one spelling. Ada and ada look like one person to everyone reading them, so lowercase a name before you store it and before you look it up:

const email = String(req.body.email ?? '').trim().toLowerCase();
if (await subscribers.findOne({ email })) {
    return res.status(409).json({ error: 'Already subscribed' });
}
challenge icon

Challenge

Easy

Right now anyone can sign up twice with the same name, or with the password 1. Make signup check what it receives before it saves anything.

  1. In server.js, at the start of POST /signup, clean up the username: remove the spaces around it and make it lowercase, so " Ada " becomes "ada". A missing username becomes an empty name.
  2. Still in POST /signup: when the name is empty, or the password has fewer than 8 characters, respond with status 400 and {"error": "Pick a username and a password of at least 8 characters"}. A password of exactly 8 characters is long enough.
  3. When a user with that cleaned name already exists, respond with status 409 and {"error": "That username is taken"}.
  4. Otherwise, save the user under the lowercase name. The 201 response shows that saved name: {"username": "ada"}, even when the request said "Ada".
  5. In POST /login, clean the username the same way before you look it up. Then ADA can log in to the account ada.

Try it: Press Run.

  • Send POST /signup with {"username": "Ada", "password": "correct horse"}: status 201 and {"username": "ada"}.
  • Send POST /signup with {"username": "ada", "password": "another password"}: status 409 and the "taken" error.
  • Send POST /login with {"username": "ADA", "password": "correct horse"}: status 200 and {"username": "ada"}.
  • Send POST /signup with {"username": "bob", "password": "1234"}: status 400.
  • Send POST /signup with only {"password": "correct horse"}: status 400 too.

Try it yourself

import express from 'express';
import { users } from './db.js';
import { hashPassword, verifyPassword } from './passwords.js';

const app = express();
app.use(express.json());

app.post('/signup', async (req, res) => {
    const { username, password } = req.body;
    await users.insertOne({ username, passwordHash: await hashPassword(password) });
    res.status(201).json({ username });
});

app.post('/login', async (req, res) => {
    const { username, password } = req.body;
    const user = await users.findOne({ username });
    if (!user || !(await verifyPassword(password, user.passwordHash))) {
        return res.status(401).json({ error: 'Wrong username or password' });
    }
    res.json({ username: user.username });
});

// Shows what signup stored. For learning only: a real app never has this route.
app.get('/debug/users/:username', async (req, res) => {
    const user = await users.findOne({ username: req.params.username });
    res.json(user ? { username: user.username, passwordHash: user.passwordHash } : null);
});

app.listen(3000, () => {
    console.log('Vault is running on port 3000');
});
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Auth and Security

Practice on your own: Express playground