*****************************USER AUTHENTICATION **************************************
TO IMPLEMENT USER AUTHENTICATION WE USE AN ARTICLE PUBLISHED ON FREECODECAMP Link to article
WE FOLLOW THE STEP BY STEP PROCESS .
WE BEGIN WITH INSTALLING THE REQUIRED PACKAGES FOR THE PROCESS.
npm i bcryptjs jsonwebtoken
CONNECTING BACKEND TO FRONTEND
INDEX.JS
cors({
origin: ["http://localhost:3000"],
methods: ["GET", "POST", "PUT", "DELETE"],
credentials: true,
})
);
WE WILL CREATE AN USER MODEL
USERSCHEMA.JS
const { Schema } = require("mongoose");
const bcrypt = require("bcryptjs");
const UserSchema = new Schema({
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true
},
username: {
type: String,
required: true,
},
createdAt: {
type: Date,
default: new Date(),
},
});
UserSchema.pre("save", async function () {
this.password = await bcrypt.hash(this.password, 12);
});
module.exports = { UserSchema };
USERMODEL.JS
const { model } = require("mongoose");
const { UserSchema } = require("../Schemas/UserSchema");
const UserModel = new model("user", UserSchema);
module.exports = { UserModel };
WE CREATE A TOKEN KEY TO CREATE SESSION FOR COOKIES.
.ENV
TOKEN_KEY=******
SECRETTOKEN.JS
require("dotenv").config();
const jwt = require("jsonwebtoken");
module.exports.createSecretToken = (id) => {
return jwt.sign({ id }, process.env.TOKEN_KEY, {
expiresIn: 3 * 24 * 60 * 60,
});
};
TO CREATE SIGNUP ,
IN INDEX.JS
ROUTE
app.post("/signup", async (req, res, next) => {
try {
console.log(req.body);
const { email, username, password, createdAt } = req.body;
if (!email || !password || !username) {
return res.json({ message: "All fields are required" });
}
const existingUser = await UserModel.findOne({ email });
if (existingUser) {
return res.json({ message: "User already exists" });
}
const user = await UserModel.create({
email,
password,
username,
createdAt,
});
const token = createSecretToken(user._id);
res.cookie("token", token, {
withCredentials: true,
httpOnly: false,
});
res
.status(201)
.json({ message: "user signed in successfully!!", success: true, user });
next();
} catch (err) {
console.error(err);
}
});
SIGNUP.JS
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import axios from "axios";
import { ToastContainer, toast } from "react-toastify";
import "../Auth.css";
const Signup = () => {
const navigate = useNavigate();
const [inputValue, setInputValue] = useState({
email: "",
password: "",
username: "",
});
const { email, password, username } = inputValue;
const handleOnChange = (e) => {
const { name, value } = e.target;
setInputValue({
...inputValue,
[name]: value,
});
};
const handleError = (err) =>
toast.error(err, {
position: "bottom-left",
});
const handleSuccess = (msg) =>
toast.success(msg, {
position: "bottom-right",
});
const handleSubmit = async (e) => {
e.preventDefault();
try {
const { data } = await axios.post(
"http://localhost:3002/signup",
{
...inputValue,
},
{ withCredentials: true }
);
console.log(data);
const { success, message } = data;
if (success) {
handleSuccess(message);
setTimeout(() => {
navigate("/");
}, 1000);
} else {
console.log(data.message);
handleError(message);
}
} catch (error) {
console.log(error);
}
setInputValue({
...inputValue,
email: "",
password: "",
username: "",
});
};
return (
<div className="authWindow">
<div className="form_container m-5 ">
<h2>Signup Account</h2>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="email">Email</label>
<input
type="email"
name="email"
value={email}
placeholder="Enter your email"
onChange={handleOnChange}
/>
</div>
<div>
<label htmlFor="email">Username</label>
<input
type="text"
name="username"
value={username}
placeholder="Enter your username"
onChange={handleOnChange}
/>
</div>
<div>
<label htmlFor="password">Password</label>
<input
type="password"
name="password"
value={password}
placeholder="Enter your password"
onChange={handleOnChange}
/>
</div>
<button type="submit">Submit</button>
<span>
Already have an account? <Link to={"/login"}>Login</Link>
</span>
</form>
<ToastContainer />
</div>
</div>
);
};
export default Signup;
IN A SIMILAR WAY LOGIN PAGE IS CREATED,
IN INDEX.JS,
app.post("/userVerification", (req, res) => {
const token = req.cookies.token;
console.log(token);
if (!token) {
return res.json({ status: false });
}
jwt.verify(token, process.env.TOKEN_KEY, async (err, data) => {
console.log(data);
if (err) {
return res.json({ status: false });
} else {
const user = await UserModel.findById(data.id);
if (user) return res.json({ status: true, user: user.username });
else return res.json({ status: false });
}
});
});
LOGINPAGE.JS
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import axios from "axios";
import { ToastContainer, toast } from "react-toastify";
import "../Auth.css";
const Login = () => {
const navigate = useNavigate();
const [inputValue, setInputValue] = useState({
email: "",
password: "",
});
const { email, password } = inputValue;
const handleOnChange = (e) => {
const { name, value } = e.target;
setInputValue({
...inputValue,
[name]: value,
});
};
const handleError = (err) =>
toast.error(err, {
position: "bottom-left",
});
const handleSuccess = (msg) =>
toast.success(msg, {
position: "bottom-left",
});
const handleSubmit = async (e) => {
e.preventDefault();
try {
const { data } = await axios.post(
"http://localhost:3002/login",
{
...inputValue,
},
{ withCredentials: true }
);
console.log(data);
const { success, message } = data;
if (success) {
handleSuccess(message);
setTimeout(() => {
navigate("/");
}, 1000);
} else {
console.log(data.message);
handleError(message);
}
} catch (error) {
console.log(error);
}
setInputValue({
...inputValue,
email: "",
password: "",
});
};
return (
<div className="authWindow mt-5">
<div className="form_container ">
<h2>Login Account</h2>
<form className="mb-5" onSubmit={handleSubmit}>
<div>
<label htmlFor="email">Email</label>
<input
type="email"
name="email"
value={email}
placeholder="Enter your email"
onChange={handleOnChange}
/>
</div>
<div>
<label htmlFor="password">Password</label>
<input
type="password"
name="password"
value={password}
placeholder="Enter your password"
onChange={handleOnChange}
/>
</div>
<button type="submit">Submit</button>
<span>
Don't have an account? <Link to={"/signup"}>Signup</Link>
</span>
</form>
<ToastContainer />
</div>
</div>
);
};
export default Login;
FOR USER VERIFICATION A MIDDLEWARE IS USED,
app.post("/userVerification", (req, res) => {
const token = req.cookies.token;
console.log(token);
if (!token) {
return res.json({ status: false });
}
jwt.verify(token, process.env.TOKEN_KEY, async (err, data) => {
console.log(data);
if (err) {
return res.json({ status: false });
} else {
const user = await UserModel.findById(data.id);
if (user) return res.json({ status: true, user: user.username });
else return res.json({ status: false });
}
});
});
STYLING IS APPLIED
AUTH.CSS
*,
::before,
::after {
box-sizing: border-box;
padding: 0;
margin: 0;
}
label {
font-size: 1.2rem;
color: #656262;
}
html,
body {
height: 100%;
width: 100%;
}
/*
body {
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(
90deg,
rgba(2, 0, 36, 1) 0%,
rgba(143, 187, 204, 1) 35%,
rgba(0, 212, 255, 1) 100%
);
font-family: Verdana, Geneva, Tahoma, sans-serif;
} */
.authWindow{
display: flex;
justify-content: center;
align-items: center;
}
.form_container {
background-color: #fff;
padding: 2rem 3rem;
border-radius: 0.5rem;
height: 20%;
width: 40%;
box-shadow: 8px 8px 24px 0px rgba(66, 68, 90, 1);
}
.form_container > h2 {
margin-block: 1rem;
padding-block: 0.6rem;
color: rgba(0, 212, 255, 1);
}
.form_container > form {
display: flex;
flex-direction: column;
gap: 1.4rem;
}
.form_container div {
display: flex;
flex-direction: column;
gap: 0.3rem;
}
.form_container input {
border: none;
padding: 0.5rem;
border-bottom: 1px solid gray;
font-size: 1.1rem;
outline: none;
}
.form_container input::placeholder {
font-size: 0.9rem;
font-style: italic;
}
.form_container button {
background-color: rgba(0, 212, 255, 1);
color: #fff;
border: none;
padding: 0.6rem;
font-size: 1rem;
cursor: pointer;
border-radius: 0.3rem;
}
span a {
text-decoration: none;
color: rgba(0, 212, 255, 1);
}
.home_page {
height: 100vh;
width: 100vw;
background: #000;
color: white;
display: flex;
justify-content: center;
align-items: center;
text-transform: uppercase;
font-size: 3rem;
flex-direction: column;
gap: 1rem;
}
.home_page span {
color: rgba(0, 212, 255, 1);
}
.home_page button {
background-color: rgb(27, 73, 83);
color: #fff;
cursor: pointer;
padding: 1rem 3rem;
font-size: 2rem;
border-radius: 2rem;
transition: ease-in 0.3s;
border: none;
}
.home_page button:hover {
background-color: rgba(0, 212, 255, 1);
}
@media only screen and (max-width: 1200px){
.home_page{
font-size: 1.5rem;
}
.home_page button {
padding: 0.6rem 1rem;
font-size: 1.5rem;
}
}
.Toastify__close-button{
background-color: red !important;
}













Comments
Post a Comment