Skip to content

Commit 82c548f

Browse files
committed
feat: jwt , refreshtoken and accesstoken with middleware
1 parent b9dfba2 commit 82c548f

File tree

4 files changed

+141
-4
lines changed

4 files changed

+141
-4
lines changed

src/controllers/user.controller.js

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@ import { ApiResponse } from "../utils/ApiResponse.js";
44
import { User } from "../models/user.models.js";
55
import { uploadOnCloudinary } from "../utils/cloudinary.js";
66

7+
const generateAccessAndRefreshTokens = async (userId) => {
8+
try {
9+
const user = await User.findById(userId);
10+
const accessToken = user.generateAccessToken();
11+
const refreshToken = user.generateRefreshToken();
12+
13+
user.refreshToken = refreshToken;
14+
await user.save({ validateBeforeSave: false });
15+
16+
return { accessToken, refreshToken };
17+
} catch (error) {
18+
throw new ApiError(
19+
500,
20+
"Something went wrong while generating refresh and access token"
21+
);
22+
}
23+
};
24+
725
const registerUser = asyncHandler(async (req, res) => {
826
// get user details from frontend
927
//validation - not empty
@@ -74,4 +92,83 @@ const registerUser = asyncHandler(async (req, res) => {
7492
.json(new ApiResponse(200, createdUser, "User Created Successfully"));
7593
});
7694

77-
export { registerUser };
95+
const loginUser = asyncHandler(async (req, res) => {
96+
// req body -> data
97+
// username or email
98+
// find the user
99+
// password check
100+
// access and refresh token
101+
//send cookie
102+
103+
const { email, username, password } = req.body;
104+
105+
if (!username || !email) {
106+
throw new ApiError(400, "username or password is required");
107+
}
108+
109+
const user = await User.findOne({
110+
$or: [{ username }, { email }],
111+
});
112+
113+
if (!user) {
114+
throw new ApiError(404, "User does not exist");
115+
}
116+
117+
const isPasswordValid = await user.isPasswordCorrect(password);
118+
119+
if (!isPasswordValid) {
120+
throw new ApiError(401, "Invalid user credentials");
121+
}
122+
const { accessToken, refreshToken } = await generateAccessAndRefreshTokens(
123+
user._id
124+
);
125+
126+
const loggedInUser = await User.findById(user._id).select(
127+
"-password -refreshToken"
128+
);
129+
const options = {
130+
httpOnly: true,
131+
secure: true,
132+
};
133+
return res
134+
.status(200)
135+
.cookie("accessToken", accessToken, options)
136+
.cookie("refreshToken", refreshToken, options)
137+
.json(
138+
// to store in local storage (not a good practice though we also send access and refresh token in json response, )
139+
// in mobile cookies are not set
140+
new ApiResponse(
141+
200,
142+
{
143+
user: loggedInUser,
144+
accessToken,
145+
refreshToken,
146+
},
147+
"User logged In Successfully"
148+
)
149+
);
150+
});
151+
152+
const logoutUser = asyncHandler(async (req, res) => {
153+
await User.findByIdAndUpdate(
154+
req.user._id,
155+
{
156+
$set: {
157+
refreshToken: undefined,
158+
},
159+
},
160+
{
161+
new: true,
162+
}
163+
);
164+
const options = {
165+
httpOnly: true,
166+
secure: true,
167+
};
168+
return res
169+
.status(200)
170+
.clearCookie("accessToken", options)
171+
.clearCookie("refreshToken", options)
172+
.json(new ApiResponse(200, {}, "User logged out"));
173+
});
174+
export { registerUser, loginUser, logoutUser };

src/middlewares/auth.middleware.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { User } from "../models/user.models";
2+
import { ApiError } from "../utils/ApiError";
3+
import { asyncHandler } from "../utils/asyncHandler";
4+
import jwt from "jsonwebtoken";
5+
6+
export const verifyJWT = asyncHandler(async (req, res, next) => {
7+
try {
8+
const token =
9+
req.cookies?.accessToken ||
10+
req.header("Authorization")?.replace("Bearer ", "");
11+
12+
if (!token) {
13+
throw new ApiError(401, "Unauthorized request");
14+
}
15+
16+
const decodedToken = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET);
17+
18+
const user = await User.findById(decodedToken?._id).select(
19+
"-password -refreshToken"
20+
);
21+
22+
if (!user) {
23+
throw new ApiError(401, "Invalid Access Token");
24+
}
25+
req.user = user;
26+
next();
27+
} catch (error) {
28+
throw new ApiError(401, error?.message || "Invalid access token");
29+
}
30+
});

src/models/user.models.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ userSchema.pre("save", async function (next) {
5959
next();
6060
});
6161

62-
// bcrypt can check if it is correct or not haha looks someone can take advantage of it
62+
// bcrypt can check if it is correct or not, haha looks like someone can take advantage of it
6363
userSchema.methods.isPasswordCorrect = async function (password) {
6464
// takes time so await
6565
return await bcrypt.compare(password, this.password);

src/routes/user.routes.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { Router } from "express";
2-
import { registerUser } from "../controllers/user.controller.js";
2+
import {
3+
loginUser,
4+
logoutUser,
5+
registerUser,
6+
} from "../controllers/user.controller.js";
37
import { upload } from "../middlewares/multer.middleware.js";
8+
import { verifyJWT } from "../middlewares/auth.middleware.js";
49

510
const router = Router();
611

@@ -19,7 +24,12 @@ router.route("/register").post(
1924
registerUser
2025
);
2126

22-
//http://localhosts:8000/api/v1/users/login
27+
router.route("/login").post(loginUser);
28+
29+
// secured routes
30+
router.route("/logout").post(verifyJWT, logoutUser);
31+
32+
//http://localhost:8000/api/v1/users/login
2333
// router.route("/login").post(login);
2434

2535
export default router;

0 commit comments

Comments
 (0)