CodeKits.devNew developer offer

React Login with Node.js and MySQL

A practical walkthrough of react login with node.js and mysql, with code excerpts, failure checks and integration guidance.

By Jonathan · 5 min read

Published

React Login with Node.js and MySQL tutorial cover
In this article

This walkthrough covers React Login with Node.js and MySQL. A React frontend, an Express backend and a dedicated MySQL development database. Use HTTPS for deployed authentication. This walkthrough shows integration excerpts rather than a drop-in identity provider.

The video is an illustrated code walkthrough with AI narration. Code blocks are integration excerpts, not a complete tested application. Helper names such as stores, middleware and clients describe responsibilities you must implement in your existing project. No live server, payment provider or device execution is claimed.

Before you begin

Use a separate development environment, fictional data and test credentials. Record dependency versions and follow the official references below for your installed versions. Keep a working baseline and add one workflow at a time.

1. Define the identity boundary

The browser collects credentials but the server decides whether they are valid. Keep user records and password hashes in the database, and return only the profile fields the interface needs. A successful login creates a new server session. Don't use a hidden page or a Boolean stored in the browser as your access control. Every protected request must be checked independently.

Define the identity boundary
Browser -> POST /api/login
Node -> password verification
MySQL -> users and hashed session identifiers
Browser <- HttpOnly session cookie

2. Design users and sessions

Use a stable user identifier, a consistently normalized email address, and a unique constraint to handle duplicate registration races. Store a password hash, never the original password. A separate session table connects a hashed random identifier to the user and an expiry time. Index the lookup fields and periodically remove expired rows. Database constraints complement application validation rather than replacing it.

Design users and sessions
CREATE TABLE users (
 id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
 email VARCHAR(254) NOT NULL UNIQUE,
 password_hash VARCHAR(255) NOT NULL
);
-- sessions: token_hash UNIQUE, user_id, expires_at

3. Hash passwords deliberately

Validate password input and bound its length before expensive processing. This excerpt uses Node's asynchronous scrypt with a random salt and explicit work parameters. Store the salt, parameters, and derived value in a versioned format so you can upgrade them later. Benchmark the cost on your deployment hardware. During verification, derive the candidate hash using the stored settings and compare equal-length buffers with a timing-safe comparison.

Hash passwords deliberately
import { randomBytes, scrypt } from "node:crypto";
import { promisify } from "node:util";
const derive = promisify(scrypt);
const salt = randomBytes(16).toString("hex");
const hash = await derive(password, salt, 64, {
 N: 32768, r: 8, p: 3, maxmem: 64 * 1024 * 1024
});

4. Create a fresh session

After verifying the credentials, generate a fresh unpredictable session token. Save its digest on the server and send the original only in the session cookie. The cookie settings shown are for secure deployment. The database must enforce the expiry as well as the browser's cookie lifetime. Rotate the session when the user logs in, and revoke the previous identifier instead of reusing it.

Create a fresh session
const raw = randomBytes(32).toString("hex");
const hash = createHash("sha256").update(raw).digest("hex");
await sessions.insert({hash, userId, expiresAt});
res.cookie("sid", raw, {
 httpOnly: true, secure: true, sameSite: "lax",
 path: "/", maxAge: 8 * 60 * 60 * 1000
});

5. Connect the React form

Submit the form to the same-origin endpoint and disable repeated submissions while it is running. Display a useful but general failure message without exposing whether an account exists. Clear the password field after the attempt. On success, reload the current-user endpoint so React reflects server state. JavaScript doesn't need to read an HttpOnly session cookie to send same-origin authenticated requests.

Connect the React form
const response = await fetch("/api/login", {
 method: "POST",
 headers: {"Content-Type": "application/json"},
 body: JSON.stringify({email, password})
});
if (!response.ok) throw new Error("Sign-in failed");
await refreshCurrentUser();

6. Protect reads and mutations

Authentication middleware should resolve the session and reject expired or revoked entries before a handler accesses private records. State-changing routes also need a suitable request forgery defence, such as a correctly enforced origin policy and token strategy for your architecture. Add rate limits and monitoring around authentication. Never treat a cookie's presence alone as proof that a valid session exists.

Protect reads and mutations
app.get("/api/me", requireSession, currentUser);
app.post("/api/logout",
 requireAllowedOrigin, requireSession, logout);
// requireSession: digest cookie, look up session,
// reject missing/expired/revoked entries.

7. Make logout invalidate access

Logout must remove the server-side session and clear the matching browser cookie. Clearing React state alone leaves a usable credential behind. Decide whether password changes should revoke every session, and provide that behaviour explicitly. Test logout by retrying a protected endpoint with the old session identifier. It must fail even if a client keeps a copy of the previous cookie.

Make logout invalidate access
await sessions.remove(currentSessionHash);
res.clearCookie("sid", {
 httpOnly: true, secure: true, sameSite: "lax", path: "/"
});
res.status(204).end();

Integration checks

Check registration validation, duplicate email, wrong password, expired sessions, forged origins, rate limits and reuse after logout. Verify the actual database adapter and HTTPS cookie behaviour in a browser.

These are verification instructions, not reported test results. The excerpts have not been executed as a complete integrated application. Review authentication, database schema, dependency versions and operational settings before deployment.

Official references

Explore CodeKits development services.