A full-stack MERN authentication starter that keeps a JWT in an HTTP-only cookie, pairs an Express/Mongo backend with a React/Redux Toolkit frontend, and ships with sign in, sign up, logout, and profile management flows.
- Register and log in users using hashed passwords plus JWTs delivered via cookies for automatic authentication checks.
- Redux Toolkit + RTK Query power API calls, caching, and
localStoragepersistence of the signed-in user state. - React Router v7 routes include protected profile access and client-side redirects for signed-in users.
- React Bootstrap, icons, and Toastify provide the UI scaffolding and feedback components used across the hero, forms, and header.
- Entry point:
server/server.jswires Express middleware, database connection, routes, and error handlers. - Routes:
server/routes/userRoutes.jsdeclares the publicPOST /api/users,POST /api/users/auth, andPOST /api/users/logoutendpoints plusGET/PUT /api/users/profileguarded byprotectmiddleware. - Authentication:
server/controller/userController.jshandles registration, login, logout, and profile updates whilegenerateToken()writes a 30-day JWT cookie (httpOnly,securein prod,sameSite: strict). - Security: Passwords are hashed with
bcryptjs(userModelpre-save hook) andauthMiddlewaredecodes cookies viajsonwebtokento populatereq.user. - Error handling:
errorMiddlewaresends JSON errors and converts MongooseCastErrors into 404s.
- Entry point:
client/src/main.jsxbootstraps React, Redux store, and defines routes withcreateBrowserRouter. - Layout:
App.jsxrenders theHeader,ToastContainer, and routerOutletwrapped in a Bootstrap container. - Pages:
/shows theHerocard,/loginand/registershow Bootstrap forms, and/profileallows authenticated users to update their info. - State:
client/src/slices/authSlice.jsholds the persisteduserInfoobject;usersApiSliceenhances the baseapiSlicewith mutations for login/register/logout/update. - Protected routes:
PrivateRouterenders children only whenuserInfoexists, otherwise it redirects to/login.
- Node.js (v18+) and npm
- A MongoDB instance (local or hosted)
- Server
cd server npm install - Client
cd ../client npm install
Copy server/.env (shown below) to configure your secrets.
NODE_ENV=development
PORT=5000
MONGO_URI=mongodb://localhost:27017/MERNAuth
JWT_SECRET=<replace-with-a-long-random-string>
MONGO_URIcan point to a remote cluster;mongoose.connectlogs the host on success.JWT_SECRETsecures the JWT cookies; rotate it before deploying.- The client relies on Vite proxying
/apitohttp://localhost:5000(seeclient/vite.config.js).
Open two shells:
-
Starts Express with
cd server npm run devnodemonon port 5000 and loads.env. -
Runs Vite on port 3000 and proxies
cd client npm run dev/apito the backend, so the frontend can call/api/userswithout CORS setup.
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/users |
POST | Public | Register a new user (name, email, password). Returns user data and sets the JWT cookie. |
/api/users/auth |
POST | Public | Login (email, password). Validates credentials and sets the JWT cookie. |
/api/users/logout |
POST | Public | Clears the jwt cookie so the browser forgets the session. |
/api/users/profile |
GET | Protected | Returns the authenticated user (uses cookie). Requires protect middleware. |
/api/users/profile |
PUT | Protected | Updates name, email, and optionally password. Returns the updated user and refreshes the cookie. |
Errors are thrown with express-async-handler; errorMiddleware formats the message and includes the stack trace unless NODE_ENV=production.
- Brad Traversy — inspiration from Traversy Media's MERN authentication tutorials and community resources.