Reputation: 21
I'm trying to send an Put request to my backend API to update a user profile info, I've implemented token-based authentication, and I'm storing the token in local storage during login. However, when I make the request to update the profile, I'm consistently getting a "401 Unauthorized" error
Can someone please help me understand why I'm still getting a "401 Unauthorized" error even though I'm sending the token in the Authorization header? Is there something I'm missing in my implementation or configuration?
The token is stored in the local storage upon successful login, and its retrieval from there for the PUT request appears to be functioning correctly. I have confirmed this by logging the token in the console and then subsequently passing it within the authorization headers
Please can someone review my code and check if there's something missing !
here's my controller
const updateUserProfile = asyncHandler(async (req, res) => {
const user = await User.findById(req.user._id);
if (user) {
user.name = req.body.name || user.name;
user.email = req.body.email || user.email;
user.tele = req.body.tele || user.tele;
user.job = req.body.job || user.job;
user.status = req.body.status || user.status;
if (req.body.password) {
user.password = req.body.password;
}
const updatedUser = await user.save();
res.json({
_id: updatedUser._id,
name: updatedUser.name,
email: updatedUser.email,
tele: updatedUser.tele,
job: updatedUser.job,
status: updatedUser.status,
token: token,
});
} else {
res.status(404).json({ message: "المستخدم غير موجود" });
}
});
and here is the authMiddleware I'm using:
import jwt from "jsonwebtoken";
import asyncHandler from "express-async-handler";
import User from "../models/useModel.js";
const protect = asyncHandler(async (req, res, next) => {
const authHeader = req.headers.authorization;
if (authHeader && authHeader.startsWith("Bearer ")) {
const token = authHeader.split(" ")[1];
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = await User.findById(decoded.userId).select("-password");
next();
} catch (error) {
console.error(error);
res.status(401);
throw new Error("Not authorized, token failed");
}
} else {
res.status(401);
throw new Error("Not authorized, no token");
}
});
export default protect;
The routes:
router
.route("/profile")
.get(protect, getUserProfile)
.put(protect,updateUserProfile);
and here the front end:
const dispatch = useDispatch();
const [updateProfile, { isLoading }] = useUpdateUserMutation({
onMutate: async (newUserData) => {
},
});
useEffect(() => {
setName(userInfo.name);
setEmail(userInfo.email);
setTele(userInfo.tele);
setJob(userInfo.job);
setStatus(userInfo.status);
}, [
userInfo.name,
userInfo.email,
userInfo.tele,
userInfo.job,
userInfo.status,
]);
const submitHandler = async (e) => {
e.preventDefault();
const token = localStorage.getItem("token");
if (password !== confirmPassword) {
toast.error("كلمات السر التي قمت بإدخالها ليست متطابقة");
} else {
try {
const res = await updateProfile(
{
_id: userInfo._id,
name,
email,
tele,
job,
status,
password,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
).unwrap();
dispatch(setCredentials({ res }));
toast.success("تم تعديل حسابك بنجاح");
} catch (err) {
toast.error(err?.data?.message || err.error);
}
}
};
export default Profile;
Upvotes: 0
Views: 243
Reputation: 37
Check in the network tab if the authorization header is passed along the request, and also in the protect middleware try to console.log authHeader and see what you get there.
Upvotes: 0