Skip to content

Commit

Permalink
add remember me
Browse files Browse the repository at this point in the history
  • Loading branch information
haseebzaki-07 committed Oct 30, 2024
1 parent e6b2d03 commit c0ceedb
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 24 deletions.
12 changes: 0 additions & 12 deletions backend/.env.example

This file was deleted.

21 changes: 13 additions & 8 deletions backend/controller/customer.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ async function loginCustomer(req, res) {
const customerLoginSchema = z.object({
email: z.string().email("Invalid email address"),
password: z.string().min(6, "Password must be at least 6 characters long"),
rememberMe: z.boolean().optional(),
});

const validation = customerLoginSchema.safeParse(req.body);
Expand All @@ -95,7 +96,8 @@ async function loginCustomer(req, res) {
}

try {
const customer = await Customer.findOne({ email: req.body.email });
const { email, password, rememberMe } = req.body;
const customer = await Customer.findOne({ email });

if (!customer) {
return res.status(401).json({ error: "Invalid email or password" });
Expand All @@ -104,25 +106,27 @@ async function loginCustomer(req, res) {
return res.status(403).json({ error: "Account not verified. Please verify your email." });
}

const validPassword = await bcrypt.compare(req.body.password, customer.password);
const validPassword = await bcrypt.compare(password, customer.password);
if (!validPassword) {
return res.status(401).json({ error: "Invalid email or password" });
}

const payload = {
sub: customer._id, // Use `sub` as this is a standard JWT claim for subject (user ID)
sub: customer._id,
name: customer.name,
role: "customer",
email: customer.email,
};

const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: "1h" });
const token = jwt.sign(payload, process.env.JWT_SECRET, {
expiresIn: rememberMe ? "7d" : "1h", // Set token expiry based on rememberMe option
});

res.cookie("authToken", token, {
maxAge: 60 * 60 * 1000, // 1 hour
httpOnly: false, // Set to false if you need access on the frontend
secure: process.env.NODE_ENV === "production", // Set `secure: true` only in production with HTTPS
sameSite: "strict", // Use `strict` to avoid CSRF in most cases
maxAge: rememberMe ? 7 * 24 * 60 * 60 * 1000 : 60 * 60 * 1000, // 7 days or 1 hour
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "strict",
});

return res.json({
Expand All @@ -142,6 +146,7 @@ async function loginCustomer(req, res) {
}



async function resetPassword(req, res) {
const customerResetPasswordSchema = z.object({
email: z.string().email("Invalid email address"),
Expand Down
18 changes: 14 additions & 4 deletions frontend/src/components/Pages/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import photo from '../../assets/login.png';
import { Link, useNavigate } from 'react-router-dom';
import { message } from 'antd';
import Cookies from 'js-cookie';
import { FaEye } from 'react-icons/fa';
import { FaEyeSlash } from 'react-icons/fa6';
import { FaEye, FaEyeSlash } from 'react-icons/fa';

const Login = () => {
const API_URL = import.meta.env.VITE_BACKEND_URL || 'http://localhost:3000';
const [data, setData] = useState({ email: '', password: '' });
const [hidden, setHidden] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const [rememberMe, setRememberMe] = useState(false); // New state for Remember Me
const navigate = useNavigate();

const handleChange = (e) => {
Expand All @@ -29,13 +29,14 @@ const Login = () => {
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
body: JSON.stringify({ ...data, rememberMe }), // Include rememberMe in the body
});
const result = await response.json();
if (!response.ok) throw new Error(result.message || 'Login failed');

// Set cookie expiration based on Remember Me option
Cookies.set('authToken', result.token, {
expires: 1 / 24, // 1 hour
expires: rememberMe ? 7 : 1 / 24, // 7 days if Remember Me is checked, 1 hour otherwise
secure: process.env.NODE_ENV === "production",
sameSite: "strict",
});
Expand Down Expand Up @@ -101,6 +102,15 @@ const Login = () => {
</button>
</div>

<label className="flex items-center gap-2 text-sm lg:text-base">
<input
type="checkbox"
checked={rememberMe}
onChange={() => setRememberMe(!rememberMe)}
/>
Remember Me
</label>

<Link
to="/email-verify"
className="text-sm lg:text-base text-gray-500 dark:text-gray-200 hover:text-red-500 transition"
Expand Down

0 comments on commit c0ceedb

Please sign in to comment.