Skip to content

Commit b0f8f8b

Browse files
authored
Merge pull request #35 from nafiuishaaq/feat/logout
Feat/logout
2 parents 006957d + 28a49df commit b0f8f8b

3 files changed

Lines changed: 92 additions & 1 deletion

File tree

src/controllers/auth.controller.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,34 @@ const jwt = require('jsonwebtoken');
44
const User = require('../models/User.model');
55
const { sendSuccess } = require('../utils/response');
66

7+
/**
8+
* Logout user by invalidating refresh token
9+
* POST /api/auth/logout
10+
*/
11+
const logout = async (req, res, next) => {
12+
try {
13+
const userId = req.userId;
14+
15+
// Find the user and clear their refresh token
16+
const user = await User.findById(userId);
17+
if (!user) {
18+
const error = new Error('User not found');
19+
error.statusCode = 404;
20+
error.isOperational = true;
21+
return next(error);
22+
}
23+
24+
// Clear the stored refresh token
25+
user.refreshTokenHash = null;
26+
user.refreshTokenExpiresAt = null;
27+
await user.save();
28+
29+
return sendSuccess(res, {}, 200, 'Logout successful');
30+
} catch (error) {
31+
return next(error);
32+
}
33+
};
34+
735
/**
836
* Register a new user
937
* POST /api/auth/register
@@ -181,5 +209,6 @@ const resetPassword = async (req, res, next) => {
181209
module.exports = {
182210
register,
183211
login,
212+
logout,
184213
resetPassword,
185214
};

src/middlewares/auth.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const jwt = require('jsonwebtoken');
2+
const User = require('../models/User.model');
3+
4+
/**
5+
* Authentication middleware - verifies JWT token and attaches user to request
6+
*/
7+
const authenticate = async (req, res, next) => {
8+
try {
9+
// Get token from Authorization header
10+
const authHeader = req.headers.authorization;
11+
if (!authHeader || !authHeader.startsWith('Bearer ')) {
12+
const error = new Error('Authentication required');
13+
error.statusCode = 401;
14+
error.isOperational = true;
15+
return next(error);
16+
}
17+
18+
const token = authHeader.substring(7); // Remove 'Bearer ' prefix
19+
20+
// Verify the token
21+
const decoded = jwt.verify(token, process.env.JWT_SECRET);
22+
23+
// Check if token is an access token
24+
if (decoded.type !== 'access') {
25+
const error = new Error('Invalid token type');
26+
error.statusCode = 401;
27+
error.isOperational = true;
28+
return next(error);
29+
}
30+
31+
// Find the user
32+
const user = await User.findById(decoded.sub);
33+
if (!user) {
34+
const error = new Error('User not found');
35+
error.statusCode = 401;
36+
error.isOperational = true;
37+
return next(error);
38+
}
39+
40+
// Attach user to request object
41+
req.user = user;
42+
req.userId = user._id.toString();
43+
44+
next();
45+
} catch (error) {
46+
if (error.name === 'JsonWebTokenError') {
47+
error.message = 'Invalid token';
48+
error.statusCode = 401;
49+
error.isOperational = true;
50+
} else if (error.name === 'TokenExpiredError') {
51+
error.message = 'Token expired';
52+
error.statusCode = 401;
53+
error.isOperational = true;
54+
}
55+
next(error);
56+
}
57+
};
58+
59+
module.exports = authenticate;

src/routes/auth.routes.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const express = require('express');
2-
const { register, login, resetPassword } = require('../controllers/auth.controller');
2+
const { register, login, logout, resetPassword } = require('../controllers/auth.controller');
33
const validate = require('../middlewares/validate');
4+
const authenticate = require('../middlewares/auth');
45
const { registerSchema, loginSchema, resetPasswordSchema } = require('../validators/auth.validators');
56

67
const router = express.Router();
@@ -11,6 +12,8 @@ router.post('/register', validate(registerSchema), register);
1112
// POST /api/auth/login - Login an existing user
1213
router.post('/login', validate(loginSchema), login);
1314

15+
// POST /api/auth/logout - Logout user (requires authentication)
16+
router.post('/logout', authenticate, logout);
1417
// PATCH /api/auth/reset-password/:token - Reset user password with token
1518
router.patch('/reset-password/:token', validate(resetPasswordSchema), resetPassword);
1619

0 commit comments

Comments
 (0)