Skip to content

Intermediate · Authentication and files end to end · topic 21 of 34 · 30 min

Signup and login end to end

Explanation

Signup and login are a conversation between the browser and the server. The browser sends an email and password; the server stores only a hash of the password, never the password itself. After login the server gives the browser a session cookie, and the browser sends it back on every request so the server knows who you are.

Two new words: authentication and session

Authentication means proving who you are. In the Notes app you prove it with an email and a password. After that, the server must remember you, so you do not type the password on every click.

A session is that memory. The server makes a long random id (the session id), saves "this id belongs to user 7", and gives the id to the browser inside a cookie. A cookie is a small piece of text the browser stores and sends back to the same website automatically.

Think of it like this: Think of a big office in Bengaluru. At the gate you show your ID card once (login). The guard gives you a visitor badge (the session cookie). Inside, every door checks the badge, not your ID card again. When you leave, you return the badge (logout) and it stops working.

Signup, step by step

  1. The user fills a form: name, email and a password of at least 8 characters.
  2. The browser checks the fields for quick feedback, then sends POST /api/auth/signup with JSON.
  3. The server checks the same rules again (the browser checks can be skipped by anyone).
  4. The server hashes the password with Argon2id or bcrypt and saves name, email and password_hash in the users table.
  5. If the email already exists, the server answers 409 Conflict. Otherwise it answers 201 Created (and often logs the user in straight away).
javascript
import argon2 from 'argon2';

app.post('/api/auth/signup', async (req, res) => {
  const name = String(req.body.name || '').trim();
  const email = String(req.body.email || '').trim().toLowerCase();
  const password = String(req.body.password || '');
  if (!name || password.length < 8) {
    return res.status(400).json({ error: 'Name and a password of 8+ characters are required' });
  }
  const passwordHash = await argon2.hash(password); // Argon2id by default
  const existing = await db.findUserByEmail(email);
  if (existing) return res.status(409).json({ error: 'Email already registered' });
  const user = await db.createUser({ name, email, passwordHash });
  return res.status(201).json({ id: user.id, name: user.name });
});
Signup handler (runs on a server with Node.js and Express). Only the hash is saved.
Careful: Never store a password in plain text, and never use a fast hash like MD5 or plain SHA-256 for passwords. If your database leaks, plain or fast-hashed passwords are cracked in minutes. Argon2id and bcrypt are slow on purpose and add a random salt to each hash.

Login, the cookie and GET /api/me

StepBrowserServer
1. LoginPOST /api/auth/login with email and passwordFinds the user, checks the password against the hash
2. SessionReceives Set-Cookie: sid=...Saves a session row: random id, user id, expiry
3. Every requestSends Cookie: sid=... automaticallyLooks up the session to find the user id
4. Who am I?GET /api/me when the app loadsReturns { id, name } or 401 if no valid session
5. LogoutPOST /api/auth/logoutDeletes the session row and clears the cookie
output
Set-Cookie: sid=Jx8f...long-random-id; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=604800
HttpOnly: JavaScript cannot read it. Secure: only sent over HTTPS. SameSite=Lax: not sent on most cross-site requests. Max-Age: 7 days.
javascript
const res = await fetch('/api/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email, password }),
});
if (res.status === 401) showError('Wrong email or password');
else if (res.ok) location.href = '/notes';
Frontend login (runs in the browser). Same-site cookies are stored and sent back automatically.

Session or JWT? A JWT (JSON Web Token) is a signed token that holds the user id itself, so the server does not need a session table. But a JWT is hard to cancel before it expires. For a normal web app like Notes, a session cookie is simpler and safer. JWTs fit better when many separate services or mobile apps must check the same login.

Tip: Give the same answer, "Wrong email or password", whether the email is unknown or the password is wrong. A different message would tell an attacker which emails have accounts.

Build it yourself or use a library?

OptionWhat it isGood when
Auth.js or Better AuthOpen-source libraries you add to your own app (popular with Next.js)You want control and your users in your own database
ClerkA paid hosted service with ready login screensYou want to ship fast and accept a monthly bill as you grow
Supabase Auth or Firebase AuthLogin that comes with a hosted backend platformYou already use Supabase or Firebase
Build it yourselfYour own hashing, sessions, emailsLearning (like this course) or very special needs

Email verification and password reset

  • Both use a one-time token: a long random string, saved (better: saved as a hash) with the user id and a short expiry, such as 30 minutes.
  • The server emails a link like /reset?token=..., the user clicks it, and the server checks the token is real, unused and not expired.
  • After use, delete the token so the link cannot work twice. After a password reset, also end the old sessions.
  • On "forgot password", always reply "If this email exists, we sent a link", so nobody can test which emails are registered.

Watch the lesson

Signup and login end to end · 1/7

Signup and login end to end

Today we add login to the Notes app, from the form all the way to the database.

Prefer a video by a teacher? Find free videos on “session cookie authentication login flow explained” on YouTube ↗

In real life: Logging in to a college results site

A student signs up on a college portal with an email and password. The server stores only an Argon2id hash. On results day she logs in: the server checks the hash, creates a session and sends back an HttpOnly cookie. Each time she opens "My marks", the browser sends the cookie and the server looks up which student she is, so she sees only her own marks. When she clicks "Logout" on a shared computer in the library, the server deletes the session, and the old cookie is useless even if someone copies it.

Practice (0/3 done)

Task 1 · Code · Javascript

Write validateSignup(input) for the signup form. input has name, email and password. Return an array of the field names that are wrong, in the order name, email, password. Rules: name is not empty after trimming; email (trimmed) has text, then "@", then text, then ".", then text, with no spaces; password has at least 8 characters. Return [] when everything is fine.

Task 2 · Code · Javascript

Build an in-memory auth service: createAuth({ hash, verify, newSessionId }) returns { signup, login, me, logout }. The hash and verify functions are passed in (tests use a fake; real apps use Argon2id or bcrypt). signup(email, password): lowercase and trim the email; password shorter than 8 -> { status: 400, error: "Password too short" }; email already used -> { status: 409, error: "Email already registered" }; else save { id, email, passwordHash: hash(password) } with id = 1, 2, 3... and return { status: 201, userId: id }. login(email, password): unknown email or verify(password, passwordHash) false -> { status: 401, error: "Wrong email or password" }; else create a session with newSessionId() and return { status: 200, sessionId }. me(sessionId): valid -> { status: 200, user: { id, email } }; else { status: 401, error: "Not logged in" }. logout(sessionId): delete the session and return { status: 204 }.

Task 3 · Practice

Write the "forgot password" flow for the Notes app as numbered steps: what the user does, what the server stores, what the email contains, and what the server checks when the link is clicked.

Quick quiz

Question 1

1.What should the users table store for a password?

Question 2

2.What does the HttpOnly flag on the session cookie do?

Question 3

3.After login, how does the server know who sends GET /api/notes?

Question 4

4.A password reset link should...

Question 5

5.What does logout do on the server?

Read more (free)

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

← Previous: Keeping the screen in sync