This is a full-stack authentication system that demonstrates user registration, login, JWT token generation, bcrypt password hashing, protected backend routes, and React authentication state management.
- A user enters an email and password in the React registration form.
- The frontend sends the data to
POST /api/auth/register. - The backend checks whether the email already exists.
- If the email is new, the backend hashes the password with bcrypt.
- The hashed password is saved in MongoDB. The plain-text password is never stored.
- A user enters an email and password in the login form.
- The frontend sends the data to
POST /api/auth/login. - The backend finds the user by email.
- bcrypt compares the entered password with the stored hash.
- If the password is correct, the backend creates a JWT that expires in 24 hours.
- The frontend stores the JWT in
localStorageso login persists after refresh.
- The dashboard sends a request to
GET /api/protected. - The JWT is sent in the
Authorizationheader as a Bearer token. - The JWT middleware verifies the token using
JWT_SECRET. - If the token is valid and unexpired, the backend returns protected data.
- If the token is missing or invalid, the backend returns
401 Unauthorized.
- Node.js
- Express
- MongoDB
- Mongoose
- JSON Web Tokens
- bcryptjs
- React
- Vite
- CSS
- User registration with bcrypt password hashing
- Login with JWT generation
- Token stored in
localStorage - Protected API route with JWT middleware
- Persistent login on page refresh
- Logout functionality
-
Open a terminal in the backend folder:
cd backend -
Install backend dependencies:
npm install
-
Create
backend/.envwith these values:MONGODB_URI=mongodb+srv://imrama_db_user:REPLACE_WITH_YOUR_PASSWORD@cluster0.yosap9t.mongodb.net/authsystem?appName=Cluster0 JWT_SECRET=replace-with-a-long-random-secret PORT=5002 -
Start the backend:
npm run dev
The backend runs at http://localhost:5002.
-
Open a second terminal in the frontend folder:
cd frontend -
Install frontend dependencies:
npm install
-
Create
frontend/.env.localwith this value:VITE_API_URL=http://localhost:5002
-
Start the frontend:
npm run dev
The frontend runs at http://localhost:5173.
- Passwords are never stored in plain text.
- bcrypt hashes passwords before they are saved to MongoDB.
- Protected routes require a valid, unexpired JWT.
- Environment variables are ignored by Git so secrets are not committed.