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
The table of contents is too big for display.
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=5000
MONGO_URI=mongodb://localhost:27017/authsystem
JWT_SECRET=Nitesh_Kumar
173 changes: 173 additions & 0 deletions backend/backend-task-User-Auth.postman_collection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
{
"info": {
"_postman_id": "fcc03046-e2b2-4047-8c6c-e72a42e2620d",
"name": "backend-task-User-Auth",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "45566835",
"_collection_link": "https://dark-resonance-3413802.postman.co/workspace/Name.surname's-Workspace~e25bd057-4a9c-4811-88d4-43e4c4b874e3/collection/45566835-fcc03046-e2b2-4047-8c6c-e72a42e2620d?action=share&source=collection_link&creator=45566835"
},
"item": [
{
"name": "auth",
"item": [
{
"name": "Registration",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"fullname\":\"Nabc\",\n \"email\":\"abc@gmail.com\",\n \"password\":\"abc\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:5000//auth/register",
"protocol": "http",
"host": [
"localhost"
],
"port": "5000",
"path": [
"",
"auth",
"register"
]
}
},
"response": []
},
{
"name": "Login",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"email\":\"N@gmail.com\",\n \"password\":\"N\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:5000/api/auth/login",
"protocol": "http",
"host": [
"localhost"
],
"port": "5000",
"path": [
"api",
"auth",
"login"
]
}
},
"response": []
},
{
"name": "Reset Password",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"email\":\"abc@gmail.com\",\n \"password\": \"abc\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:5000/auth/reset-password",
"protocol": "http",
"host": [
"localhost"
],
"port": "5000",
"path": [
"auth",
"reset-password"
]
}
},
"response": []
},
{
"name": "New password",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "8cc7daa47d5e797dcc151f13333577db7edc1197d7f3636719189f9b19ddc38c",
"type": "string"
}
]
},
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"password\": \"abc\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:5000/auth/new-Password",
"protocol": "http",
"host": [
"localhost"
],
"port": "5000",
"path": [
"auth",
"new-Password"
]
}
},
"response": []
}
]
},
{
"name": "user",
"item": [
{
"name": "Profile",
"request": {
"method": "GET",
"header": []
},
"response": []
}
]
},
{
"name": "health_check",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:5000",
"protocol": "http",
"host": [
"localhost"
],
"port": "5000"
}
},
"response": []
}
]
}
13 changes: 13 additions & 0 deletions backend/config/db.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.MONGO_URI);
console.log("MongoDB Connected");
} catch (err) {
console.error("Database connection error:", err.message);
process.exit(1);
}
};

module.exports = connectDB;
153 changes: 153 additions & 0 deletions backend/controllers/auth.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
const User = require("../models/user.model");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const crypto = require("crypto");
const resetTokens = new Map();

// Register User
exports.registerUser = async (req, res) => {
try {
const { fullname, email, password } = req.body;

let user = await User.findOne({ email });
if (user) return res.status(400).json({ message: "User already exists" });

const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);

user = new User({ fullname, email, password: hashedPassword });
await user.save();

const payload = { user: { id: user.id } };
jwt.sign(
payload,
process.env.JWT_SECRET,
{ expiresIn: "7d" },
(err, token) => {
if (err) throw err;
res.json({ token });
},
);
} catch (err) {
res.status(500).send("Server error");
}
};

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

const user = await User.findOne({ email });
if (!user) return res.status(400).json({ message: "Invalid credentials" });

const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch)
return res.status(400).json({ message: "Invalid credentials" });

const payload = { user: { id: user.id } };
jwt.sign(
payload,
process.env.JWT_SECRET,
{ expiresIn: "7d" },
(err, token) => {
if (err) throw err;
res.json({ token });
},
);
} catch (err) {
res.status(500).send("Server error");
}
};

// Reset password
exports.resetPassword = async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(404).json({
success: false,
message: "User not found",
});
}

const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(401).json({
success: false,
message: "Current password is incorrect",
});
}

const authKey = crypto.randomBytes(32).toString("hex");
const expiresAt = new Date(Date.now() + 15 * 60 * 1000);

resetTokens.set(authKey, {
userId: user._id,
expiresAt,
});

res.json({
success: true,
message: "Authentication key generated",
authKey,
expiresAt,
});
} catch (err) {
res.status(500).json({
success: false,
message: "Server error during password reset",
error: err.message,
});
}
};

// New Password
exports.newPassword = async (req, res) => {
try {
// Get authKey from headers
const authKey = req.headers.authorization?.split(" ")[1];
const { password } = req.body;

if (!authKey) {
return res.status(401).json({
success: false,
message: "Authentication key is missing",
});
}

const tokenData = resetTokens.get(authKey);
if (!tokenData || tokenData.expiresAt < new Date()) {
return res.status(400).json({
success: false,
message: "Invalid or expired authentication key",
});
}

const user = await User.findById(tokenData.userId);
if (!user) {
return res.status(404).json({
success: false,
message: "User not found",
});
}

const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();

resetTokens.delete(authKey);

res.json({
success: true,
message: "Password updated successfully",
});
} catch (err) {
res.status(500).json({
success: false,
message: "Server error during password update",
error: err.message,
});
}
};
6 changes: 6 additions & 0 deletions backend/controllers/healthController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
exports.healthCheck = (req, res) => {
res.json({
status: "OK",
message: "backend-task-User-Auth is running smoothly!",
});
};
19 changes: 19 additions & 0 deletions backend/controllers/user.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const User = require("../models/user.model");

exports.getUserProfile = async (req, res) => {
try {
const user = await User.findById(req.user.id).select(
"-password -__v -createdAt -updatedAt",
);

res.json({
success: true,
data: user,
});
} catch (err) {
res.status(500).json({
success: false,
message: "Server error fetching profile",
});
}
};
19 changes: 19 additions & 0 deletions backend/middleware/auth.middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const jwt = require("jsonwebtoken");

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

if (!authHeader || !authHeader.startsWith("Bearer ")) {
return res.status(401).json({ message: "No token, authorization denied" });
}

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

try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded.user;
next();
} catch (err) {
res.status(401).json({ message: "Token is not valid" });
}
};
Loading