*****************************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

Popular posts from this blog

CONNECTING MONGODB WITH EXPRESS

SETTING UP REACT ROUTER

*********UPDATING THE FRONTEND*********