Reputation: 1
the problem i am facing is that everything works fine locally but when it comes to production it gives this error ...
...front end code
import React, { useState } from 'react';
import { motion } from 'framer-motion';
import { axiosInstance } from '../../lib/axio';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../../context/AuthContext';
const AuthPage = () => {
const navigate = useNavigate();
const { login } = useAuth();
const [isLogin, setIsLogin] = useState(true);
const [name, setName] = useState('');
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleOnSubmit = async (e) => {
e.preventDefault();
if (!username || !password) {
alert('All fields are required.');
return;
}
if (isLogin) {
try {
// Simulate an API request for login
// Replace this with your actual login logic, such as an API call to check credentials
const response = await axiosInstance.post('/user/login', { username, password });
console.log("login response:", response);
if (response.status === 200) {
login();
alert("Logged in successfully!");
navigate("/blogs/create");
window.scrollTo(0, 0);
} else {
alert(response.data.message);
console.log("response error : ", response);
}
} catch (error) {
alert(error.response?.data?.message || 'Unable to log in. Check your credentials.');
console.log(error)
}
}
else {
try {
const response = await axiosInstance.post("/user/signup", {
name,
username,
password,
});
console.log("signup response:", response);
if (response.status === 201) {
login();
alert("Signed up successfully!");
navigate('/blogs/create')
window.scrollTo(0, 0);
} else {
alert(response.data.message || 'Something went wrong. Please try again.');
}
} catch (error) {
alert(error.response?.data?.message || 'Unable to sign up. Please try again.');
}
}
}
const toggleAuthMode = () => {
setIsLogin((prevMode) => !prevMode);
};
return (
<div className="flex justify-center items-center h-screen bg-gradient-to-r from-blue-500 via-purple-500 to-pink-500">
<motion.div
className="w-full max-w-md p-6"
initial={{ opacity: 0, y: 50 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<div className="bg-white shadow-2xl rounded-2xl">
<div className="p-8">
<h2 className="text-2xl font-bold text-center mb-6 text-gray-800">
{isLogin ? 'Login' : 'Sign Up'}
</h2>
<form onSubmit={handleOnSubmit}>
{!isLogin && (
<div className="mb-4">
<label htmlFor="name" className="block text-gray-700 text-sm font-bold mb-2">
Name
</label>
<input
type="text"
id="name"
value={name}
onChange={(e) => { setName(e.target.value) }}
className="w-full px-3 py-2 text-gray-700 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter your name"
/>
</div>
)}
<div className="mb-4">
<label htmlFor="username" className="block text-gray-700 text-sm font-bold mb-2">
username
</label>
<input
type="username"
id="username"
value={username}
onChange={(e) => { setUsername(e.target.value) }}
className="w-full px-3 py-2 text-gray-700 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter your username"
/>
</div>
<div className="mb-4">
<label htmlFor="password" className="block text-gray-700 text-sm font-bold mb-2">
Password
</label>
<input
type="password"
id="password"
value={password}
onChange={(e) => { setPassword(e.target.value) }}
className="w-full px-3 py-2 text-gray-700 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400"
placeholder="Enter your password"
/>
</div>
<button className="w-full py-2 text-white bg-blue-600 hover:bg-blue-700 rounded-lg">
{isLogin ? 'Login' : 'Sign Up'}
</button>
</form>
<p className="text-center text-sm text-gray-600 mt-4">
{isLogin ? "Don't have an account?" : 'Already have an account?'}{' '}
<button
onClick={toggleAuthMode}
className="text-blue-600 hover:underline focus:outline-none"
>
{isLogin ? 'Sign Up' : 'Login'}
</button>
</p>
</div>
</div>
</motion.div>
</div>
);
};
export default AuthPage;
authMiddleware
const jwt = require("jsonwebtoken");
const User = require("../models/User");
const protectRoute = async (req, res, next) => {
try {
const token = req.cookies["jwt-booklore-blog"];
console.log("token:", token);
if (!token) {
return res.status(401).json({ message: "Unauthorized - No Token Provided", success: false });
}
const decoded = jwt.verify(token, process.env.JWT_SECRET);
console.log("decoded:", decoded);
if (!decoded) {
return res.status(401).json({ message: "Unauthorized - Invalid Token", success: false });
}
const user = await User.findById(decoded.userId).select("-password");
if (!user) {
return res.status(401).json({ message: "User not found", success: false });
}
req.user = user;
next();
} catch (error) {
console.log("Error in protectRoute middleware:", error.message);
if (error.name === 'TokenExpiredError') {
return res.status(401).json({ message: 'Token expired', success: false });
} else if (error.name === 'JsonWebTokenError') {
return res.status(401).json({ message: 'Invalid token', success: false });
} else {
return res.status(500).json({ message: "Internal server error", success: false });
}
}
};
module.exports = { protectRoute };
authController
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const User = require("../models/User");
const signup = async (req, res) => {
try {
const { name, username, password } = req.body;
if (!name || !username || !password) {
return res.status(400).json({ message: "All fields are required" });
}
const existingUsername = await User.findOne({ username });
if (existingUsername) {
return res.status(400).json({ message: "Username already exists" });
}
if (password.length < 6) {
return res.status(400).json({ message: "Password must be at least 6 characters" });
}
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
const user = new User({
name,
username,
password: hashedPassword,
});
await user.save();
const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: "30d" });
res.cookie("jwt-booklore-blog", token, {
httpOnly: true, // prevent XSS attack
maxAge: 30 * 24 * 60 * 60 * 1000,
sameSite: "strict", // prevent CSRF attacks,
secure: process.env.NODE_ENV === "production", // prevents man-in-the-middle attacks
});
res.status(201).json({ message: "User registered successfully", success: true, reDirectUrl: '/' });
// const profileUrl = process.env.CLIENT_URL + "/profile/" + user.username;
// try {
// await sendWelcomeEmail(user.email, user.name, profileUrl);
// } catch (emailError) {
// console.error("Error sending welcome Email", emailError);
// }
} catch (error) {
console.log("Error in signup: ", error);
res.status(500).json({ message: "Internal server error", reDirectUrl: '/', success: false });
}
};
const login = async (req, res) => {
try {
const { username, password } = req.body;
// Check if user exists
const user = await User.findOne({ username });
if (!user) {
return res.status(400).json({ message: "Invalid username", success: false });
}
// Check password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ message: "Invalid Password", success: false });
}
// Create and send token
const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: "30d" });
await res.cookie("jwt-booklore-blog", token, {
httpOnly: true,
maxAge: 30 * 24 * 60 * 60 * 1000,
sameSite: "strict",
secure: process.env.NODE_ENV === "production",
});
console.log("Cookie set:", req.cookies["jwt-booklore-blog"])
res.json({ message: "Logged in successfully", success: true, reDirectUrl: '/' });
} catch (error) {
console.error("Error in login controller:", error);
res.status(500).json({ message: "Server error", success: false });
}
};
const logout = (req, res) => {
res.clearCookie("jwt-booklore-blog");
res.json({ message: "Logged out successfully", success: true, reDirectUrl: '/' });
};
const getCurrentUser = async (req, res) => {
try {
console.log("Current User: ", req.user);
res.json(req.user);
} catch (error) {
console.error("Error in getCurrentUser controller:", error);
res.status(500).json({ message: "Server error", success: false });
}
};
module.exports = { signup, login, logout, getCurrentUser };
..everything works locally .. but after production this error is coming .... if tried the secure:false....adding domain in cookie .. i tried everything i can .. still stuck
... expecting to work everything on production
Upvotes: 0
Views: 31
Reputation: 11
1) The issue might be related to http only cookie being set with same site 'strict'. If you have seperate domains for FE and BE on production then you need to change same site to none and secure to true in your cookie configurations:
res.cookie("jwt-booklore-blog", token, {
httpOnly: true,
maxAge: 30 * 24 * 60 * 60 * 1000,
sameSite: "none", // For cross-domain
secure: true //this should be true on production if sameSite is none
});
2) Also make sure core is enabled on backend, head over to your index.js/main.js file on BE and write this
app.use(cors({ origin: process.env.CLIENT_URL, credentials: true }));
3. In order to send cookies from FE to server you need to include "withCredentials: true" with your axios request, easy way is to add this your axios instance
const axiosInstance = axios.create({
baseURL: process.env.REACT_APP_API_BASE_URL,
withCredentials: true, // Send cookies
});
Upvotes: 0