Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backend/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
PORT=3000
MONGODB_URI=mongodb://127.0.0.1:27017/auth-task
JWT_SECRET=yourSuperSecretKey
11 changes: 11 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules/

.env

.vscode/

package-lock.json

*.log

.DS_Store
13 changes: 13 additions & 0 deletions backend/config/db.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const mongoose = require('mongoose');

const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGODB_URI);
console.log('MongoDB connected');
} catch (error) {
console.error('MongoDB connection failed:', error.message);
process.exit(1);
}
};

module.exports = connectDB;
90 changes: 90 additions & 0 deletions backend/controllers/auth.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
const jwt = require('jsonwebtoken');
const User = require('../models/user.model');

// Register
exports.register = async (req, res) => {
const { fullName, email, password } = req.body;

try {
const existingUser = await User.findOne({ email });
if (existingUser) return res.status(400).json({ error: 'Email already registered' });

const newUser = new User({ fullName, email, password });
await newUser.save();
res.status(201).json({ message: 'User registered successfully' });
} catch (err) {
res.status(500).json({ error: 'Server error during registration' });
}
};

// Login
exports.login = async (req, res) => {
const { email, password } = req.body;

try {
const user = await User.findOne({ email });
if (!user || user.password !== password) {
return res.status(401).json({ error: 'Invalid email or password' });
}

const payload = { userId: user._id };
const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '1h' });

res.status(200).json({
message: 'Login successful',
token,
expiresIn: 3600, // 1 hour in seconds
user: {
fullName: user.fullName,
email: user.email,
isEmailVerified: user.isEmailVerified
}
});
} catch (err) {
res.status(500).json({ error: 'Server error during login' });
}
};


// reset password token
exports.resetPasswordRequest = async (req, res) => {
const { email } = req.body;

try {
const user = await User.findOne({ email });
if (!user) return res.status(404).json({ error: 'User not found' });

const resetToken = jwt.sign(
{ userId: user._id },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);

res.json({ message: 'Reset token generated', resetToken });
} catch (err) {
res.status(500).json({ error: 'Server error' });
}
};

// Set new password
exports.setNewPassword = async (req, res) => {
const { token, newPassword } = req.body;

try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findById(decoded.userId);
if (!user) return res.status(404).json({ error: 'User not found' });

user.password = newPassword;
await user.save();

res.json({ message: 'Password has been updated' });
} catch (err) {
res.status(400).json({ error: 'Invalid or expired token' });
}
};

// Logout
exports.logout = async (req, res) => {
res.status(200).json({ message: 'Logged out successfully' });
};
32 changes: 32 additions & 0 deletions backend/middleware/auth.middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const jwt = require('jsonwebtoken');

module.exports = (req, res, next) => {
const authHeader = req.headers.authorization;


if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'Authorization token missing' });
}

const token = authHeader.split(' ')[1];

try {
// Verify token
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.userId = decoded.userId;
next();
} catch (error) {
// Handle expired token
if (error.name === 'TokenExpiredError') {
return res.status(401).json({ error: 'Token has expired. Please log in again.' });
}

// Handle invalid token
if (error.name === 'JsonWebTokenError') {
return res.status(401).json({ error: 'Invalid token. Authentication failed.' });
}

// Generic error fallback
return res.status(401).json({ error: 'Unauthorized access' });
}
};
26 changes: 26 additions & 0 deletions backend/models/user.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
fullName: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
unique: true,
lowercase: true,
trim: true
},
password: {
type: String,
required: true
},
isEmailVerified: {
type: Boolean,
default: false
}
}, { timestamps: true });

module.exports = mongoose.model('User', userSchema);
Loading