Absolutely, Suchit! Here's a simple and secure authentication API using Node.
js,
Express, MongoDB, and JWT for your Expense Tracker application. It includes:
User Signup
User Login
User Logout (client side)
Token-based protection
Password hashing using bcrypt
Folder Structure (recommended)
expense-tracker-api/
│
├── controllers/
│ └── authController.js
├── models/
│ └── User.js
├── routes/
│ └── authRoutes.js
├── middleware/
│ └── authMiddleware.js
├── .env
├── server.js
└── package.json
1. package.json dependencies
npm init -y
npm install express mongoose bcryptjs jsonwebtoken dotenv cors
2. .env (for environment variables)
PORT=5000
MONGO_URI=mongodb://127.0.0.1:27017/ExpenseTracker
JWT_SECRET=yourSuperSecretKey
3. models/User.js
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
username: { type: String, required: true, trim: true },
email: { type: String, required: true, unique: true, lowercase: true },
password: { type: String, required: true },
});
module.exports = mongoose.model("User", userSchema);
4. controllers/authController.js
const User = require("../models/User");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const signup = async (req, res) => {
try {
const { username, email, password } = req.body;
const exists = await User.findOne({ email });
if (exists) return res.status(400).json({ message: "User already exists" });
const hashedPassword = await bcrypt.hash(password, 10);
const user = await User.create({ username, email, password: hashedPassword });
res.status(201).json({ message: "User registered successfully", user: { id:
user._id, email: user.email } });
} catch (err) {
res.status(500).json({ error: err.message });
}
};
const login = async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) return res.status(404).json({ message: "User not found" });
const validPass = await bcrypt.compare(password, user.password);
if (!validPass) return res.status(401).json({ message: "Invalid password" });
const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: "1d"
});
res.status(200).json({ token, user: { id: user._id, username: user.username,
email: user.email } });
} catch (err) {
res.status(500).json({ error: err.message });
}
};
module.exports = { signup, login };
5. routes/authRoutes.js
const express = require("express");
const router = express.Router();
const { signup, login } = require("../controllers/authController");
router.post("/signup", signup);
router.post("/login", login);
module.exports = router;
6. middleware/authMiddleware.js (protect routes)
const jwt = require("jsonwebtoken");
const verifyToken = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith("Bearer ")) return res.status(403).json({ message:
"Unauthorized" });
const token = authHeader.split(" ")[1];
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (err) {
res.status(401).json({ message: "Token invalid or expired" });
}
};
module.exports = verifyToken;
7. server.js
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const dotenv = require("dotenv");
const authRoutes = require("./routes/authRoutes");
dotenv.config();
const app = express();
app.use(cors());
app.use(express.json());
app.use("/api/auth", authRoutes);
app.get("/", (req, res) => res.send("Expense Tracker API is running..."));
mongoose.connect(process.env.MONGO_URI)
.then(() => {
app.listen(process.env.PORT, () =>
console.log(`Server started on http://localhost:${process.env.PORT}`)
);
})
.catch(err => console.error("MongoDB connection error:", err));
Example Routes:
POST /api/auth/signup
{
"username": "suchit",
"email": "[email protected]",
"password": "secure123"
}
POST /api/auth/login
{
"email": "[email protected]",
"password": "secure123"
}
Want to add more?
I can help you add:
Protected routes (like /api/expenses )
Logout (handled client-side by removing token)
Refresh token logic
Reset password with email (optional)
Let me know if you want to move forward with those or if you need help integrating
this with your React frontend!