Foundation project
Project: a secure sign-up form
Lesson 12 of 20 · 22 min · Module 3: Passwords and sessions
Put the first three modules together in a sign-up form, the kind of form many real sites get wrong. It checks what people type, enforces sensible password rules, sends the data carefully, and shows the server’s answers without trusting them.
Start this lesson →Free. No installation: you write and run the code in your browser, and it is checked automatically.
By the end, you’ll be able to…
- Combine validation, password rules and safe output in one form
- Send credentials carefully and handle every answer
- Keep passwords out of logs and storage
The idea
Check the username with an allow-list and the password with the rules you know, show the first problem next to its field, and move focus there. When everything is fine, send JSON with fetch, show the server’s answer with textContent, and never log or store the password. The form’s autocomplete values already help password managers.
const problem = usernameProblem('Ana Smith!');
if (problem) {
document.querySelector('#username-error').textContent = problem;
document.querySelector('#username').focus();
}
01Check early, check again later
Checks in the browser give instant feedback and save a request, but the server must repeat every one of them, because requests can be sent without your form.
02Answers from servers are data too
Messages in a server’s answer can contain text that came from people, such as a username someone chose. Show them with textContent, like any other untrusted text.
03Help password managers
autocomplete="username" and autocomplete="new-password" tell password managers what each field is for, so they can offer a strong generated password and fill it in later. Never block pasting into password fields.
<input type="password" autocomplete="new-password">
Your project brief
• usernameProblem(username) returns
Use 3 to 20 lowercase letters, digits or underscores. or ''.• passwordProblem(password, username) returns the first problem, or
'': Use at least 15 characters., Use 64 characters or fewer., This password is too common. (in COMMON, ignoring capitals), Do not include your username. (usernames of 3 or more characters, ignoring capitals). Count characters with [...password].length.• On submit: prevent the default, show both messages in
#username-error and #password-error, and focus the first invalid field. Otherwise disable #create and POST { username, email, password } as JSON to /api/signup. On success show Account created. Welcome, ana_92! (with the real username) and reset the form; otherwise show the answer’s error; if the request fails, show Could not reach the server. Please try again. Enable the button again at the end.• Never write the password to the console or to storage.
What the checks look for
- Invalid usernames stop the form
- Weak passwords stop the form
- The password cannot contain the username
- A valid form is sent as JSON
- Success is announced and the form cleared
- Server errors are shown as plain text
- The button waits while the request is sent
- The password stays out of logs and storage
- A lost connection is explained
Take this with you
Validate, send carefully, show answers as text, and keep passwords to yourself.
Go a little further
Before sending the form, check the password against the leaked-password list from the challenge “Has this password leaked?”.