Objectives
- Create a REST API using ExpressJS and connect it to MongoDB.
- Design and validate a user schema using Mongoose.
- Implement user registration and login endpoints.
- Generate and verify JWTs for authentication.
- Structure a microservice project using best practices.
1. Microservice Overview
- Service Name: user-service
- Responsibility: Manage all user-related operations such as registration, login, and authentication.
- Technology Stack: Node.js, ExpressJS, MongoDB (via Mongoose), JWT
2. Structure architechture
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| user-service/
├── controllers/
│ └── auth.controller.js
├── models/
│ └── user.model.js
├── routes/
│ └── auth.routes.js
├── middlewares/
│ └── validateToken.js
├── utils/
│ └── jwt.js
├── .env
├── server.js
├── package.json
|
2.1. ExpressJS Setup
Install necessary packages:
1
2
| npm init -y
npm install express mongoose dotenv jsonwebtoken bcryptjs
|
Basic Express server setup (server.js)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| const express = require('express');
const mongoose = require('mongoose');
require('dotenv').config();
const app = express();
app.use(express.json());
// Routes
app.use('/api/auth', require('./routes/auth.routes'));
mongoose.connect(process.env.MONGO_URI)
.then(() => app.listen(process.env.PORT, () => {
console.log(`User service running on port ${process.env.PORT}`);
}))
.catch(err => console.error(err));
|
2.2. User Schema (Mongoose)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| // models/user.model.js
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const userSchema = new mongoose.Schema({
name: String,
email: { type: String, unique: true },
password: String,
role: { type: String, default: 'customer' }
});
userSchema.pre('save', async function(next) {
if (this.isModified('password')) {
this.password = await bcrypt.hash(this.password, 10);
}
next();
});
module.exports = mongoose.model('User', userSchema);
|
2.3 Authentication Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| // controllers/auth.controller.js
const User = require('../models/user.model');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
exports.register = async (req, res) => {
const { name, email, password } = req.body;
try {
const user = new User({ name, email, password });
await user.save();
res.status(201).json({ message: 'User registered successfully.' });
} catch (err) {
res.status(400).json({ error: 'Registration failed.' });
}
};
exports.login = async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.findOne({ email });
if (!user || !await bcrypt.compare(password, user.password))
return res.status(401).json({ error: 'Invalid credentials' });
const token = jwt.sign({ userId: user._id, role: user.role }, process.env.JWT_SECRET);
res.json({ token });
} catch (err) {
res.status(500).json({ error: 'Login failed.' });
}
};
|
2.4. Routes
1
2
3
4
5
6
7
8
| // routes/auth.routes.js
const router = require('express').Router();
const { register, login } = require('../controllers/auth.controller');
router.post('/register', register);
router.post('/login', login);
module.exports = router;
|
2.5. Environment Variables (.env)
PORT=4001
MONGO_URI=mongodb://localhost:27017/user-service
JWT_SECRET=your_jwt_secret
4. API Testing with Postman
Method | Endpoint | Payload | Description |
---|
POST | /api/auth/register | { name, email, password } | Register new user |
POST | /api/auth/login | { email, password } | Log in and receive token |
- Set Content-Type: application/json in headers.
- On successful login, copy the JWT token to use for protected routes in later epochs.