Skip to content

Commit

Permalink
Merge pull request #307 from samar12-rad/Google/oAuth
Browse files Browse the repository at this point in the history
Feat: Google/o auth using passport js #148
  • Loading branch information
RamakrushnaBiswal authored Oct 16, 2024
2 parents 9db7ffe + 40b8f83 commit 21432b1
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 64 deletions.
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,15 +279,22 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Navneet Dadhich</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Aditya90456">
<img src="https://avatars.githubusercontent.com/u/153073510?v=4" width="100;" alt="Aditya90456"/>
<br />
<sub><b>Aditya Bakshi</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/tanishirai">
<img src="https://avatars.githubusercontent.com/u/178164785?v=4" width="100;" alt="tanishirai"/>
<br />
<sub><b>Tanishi Rai</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/Picodes10">
<img src="https://avatars.githubusercontent.com/u/91375618?v=4" width="100;" alt="Picodes10"/>
Expand Down Expand Up @@ -323,15 +330,15 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>MANI </b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/Ayush215mb">
<img src="https://avatars.githubusercontent.com/u/154300084?v=4" width="100;" alt="Ayush215mb"/>
<br />
<sub><b>Ayush Yadav</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/AliGates915">
<img src="https://avatars.githubusercontent.com/u/128673394?v=4" width="100;" alt="AliGates915"/>
Expand Down Expand Up @@ -367,15 +374,15 @@ We extend our heartfelt gratitude to all the amazing contributors who have made
<sub><b>Mohit Rana </b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/MutiatBash">
<img src="https://avatars.githubusercontent.com/u/108807732?v=4" width="100;" alt="MutiatBash"/>
<br />
<sub><b>Bashua Mutiat</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/Sapna127">
<img src="https://avatars.githubusercontent.com/u/91309280?v=4" width="100;" alt="Sapna127"/>
Expand Down
5 changes: 4 additions & 1 deletion backend/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
MONGO_URI=enter_your_mongo_uri
EMAIL_USER=your_gmail
EMAIL_PASS=your_16_digit_pass
JWT_SECRET=secret
JWT_SECRET=secret
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
FRONTEND_URL=your_frontend_url
39 changes: 39 additions & 0 deletions backend/config/oauth.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const GoogleStrategy = require("passport-google-oauth20").Strategy;
const passport = require("passport");
const Customer = require("../models/customer.model"); // Adjust the path as needed
const config = require("./secret"); // Import your secrets (client ID, client secret)

passport.use(
new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID || config.GOOGLE_CLIENT_ID,
clientSecret:
process.env.GOOGLE_CLIENT_SECRET || config.GOOGLE_CLIENT_SECRET,
callbackURL: "/auth/google/callback",
},
async (accessToken, refreshToken, profile, done) => {
try {
// Extract the email from Google profile
const email = profile.emails[0].value;

// Search for the user in the database by email
let user = await Customer.findOne({ email });
if (!user) {
// If user doesn't exist, create a new user
user = new Customer({
name: profile.displayName || "Unamed User",
email: email, // Email from Google profile
});
await user.save();
}
// Return the user if exists or after creation
return done(null, user);
} catch (error) {
console.error("Error during Google authentication:", error);
return done(null, false, { message: "Authentication failed" });
}
}
)
);

module.exports = passport;
4 changes: 3 additions & 1 deletion backend/config/passport.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ const passport = require("passport");
const config = require("./secret");
const Customer = require("../models/customer.model");
const Admin = require("../models/admin.model");
require("./oauth.config");

// Secret key to sign the JWT token
const secret = config.JWT_SECRET;
const opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: secret,
secretOrKey: process.env.JWT_SECRET || secret,
algorithms: ["HS256"],
};

passport.use(
Expand Down
6 changes: 6 additions & 0 deletions backend/config/secret.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ const JWT_SECRET = process.env.JWT_SECRET;
const MONGO_URI = process.env.MONGO_URI;
const PORT = process.env.PORT;
const CORS_ORIGIN = process.env.CORS_ORIGIN;
const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID;
const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET;
const FRONTEND_URL = process.env.FRONTEND_URL;

module.exports = {
JWT_SECRET,
MONGO_URI,
PORT,
CORS_ORIGIN,
GOOGLE_CLIENT_ID,
GOOGLE_CLIENT_SECRET,
FRONTEND_URL,
};
29 changes: 29 additions & 0 deletions backend/controller/googleOAuth.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const secret = require("../config/secret");
const jwt = require("jsonwebtoken");
const jwtSecret = secret.JWT_SECRET;

const handleGoogleOAuth = async (req, res) => {
const token = jwt.sign(
{
sub: req.user._id,
email: req.user.email,
iat: Math.floor(Date.now() / 1000),
aud: "play-cafe",
},
jwtSecret,
{
expiresIn: "1d",
algorithm: "HS256",
}
);

res.cookie("authToken", token, {
maxAge: 3600000,
secure: true,
});
res.redirect(process.env.FRONTEND_URL || "http://localhost:3000");
};

module.exports = {
handleGoogleOAuth,
};
13 changes: 10 additions & 3 deletions backend/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
const express = require("express");
require("dotenv").config();
const cors = require("cors");
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const logger = require("./config/logger");
const errorMiddleware = require("./middlewares/errrorMiddleware");
const passport = require("passport");

dotenv.config();
const { handleGoogleOAuth } = require("./controller/googleOAuth.controller");
const app = express();
const port = process.env.PORT || 3000;

Expand Down Expand Up @@ -49,6 +48,14 @@ app.use(passport.initialize());

// API routes
app.use("/api", require("./routes/index"));
app.get(
"/auth/google/callback",
passport.authenticate("google", {
failureRedirect: "/login",
session: false,
}),
handleGoogleOAuth
);

app.options("*", cors(corsOptions));

Expand Down
10 changes: 3 additions & 7 deletions backend/middlewares/authAdmin.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,13 @@ const authenticateAdmin = (req, res, next) => {
if (token) {
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
console.log(decoded.role);
// Remove console.log or replace with logger.debug if needed
if (decoded.role !== "admin") {
logger.error(
`Unauthorized access to admin route: ${JSON.stringify(decoded.sub)}`
);
return res.status(401).json({ error: "Unauthorized access" });
return res.status(401).json({ error: "Forbidden" });
}
logger.info(`Admin authenticated: ${JSON.stringify(decoded.sub)}`);

next();
} catch (error) {
logger.error(`Error authenticating admin: ${error}`);
return res.status(401).json({ error: "Unauthorized access" });
}
} else {
Expand Down
1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"mongoose": "^8.7.0",
"nodemailer": "^6.9.15",
"passport": "^0.7.0",
"passport-google-oauth20": "^2.0.0",
"passport-jwt": "^4.0.1",
"validator": "^13.12.0",
"winston": "^3.14.2",
Expand Down
6 changes: 6 additions & 0 deletions backend/routes/customerRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const {
} = require("../controller/customer.controller");
const authenticateCustomer = require("../middlewares/authCustomer");
const passport = require("../config/passport.config");
const { handleGoogleOAuth } = require("../controller/googleOAuth.controller");
const router = express.Router();
require("dotenv").config();

Expand All @@ -26,6 +27,11 @@ router.get(
);

router.post("/register", createCustomer);
router.get(
"/auth/google",
passport.authenticate("google", { scope: ["email"] })
);

router.post("/login", loginCustomer);
router.post("/reset-password", resetPassword);

Expand Down
10 changes: 8 additions & 2 deletions backend/routes/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
const express = require("express");
const logger = require("../config/logger"); // Import your Winston logger
require("dotenv").config();

const config = {
JWT_SECRET: process.env.JWT_SECRET,
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET,
};

const router = express.Router();

Expand Down Expand Up @@ -46,6 +53,5 @@ router.use("/feedback", feedbackRouter);
router.use("/user", require("./customerRouter"));
router.use("/reservation", require("./reservationRouter"));
router.use("/newsletter", require("./newsletterRoute"));
router.use("/forgot", require("./forgotRouter"))

router.use("/forgot", require("./forgotRouter"));
module.exports = router;
53 changes: 33 additions & 20 deletions frontend/src/components/Pages/Login.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@

import React, { useState , useEffect } from "react";
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 React, { useState, useEffect } from 'react';
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';

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 [hidden, setHidden] = useState(true);

const handleChange = (e) => {
setData({ ...data, [e.target.name]: e.target.value });
Expand All @@ -39,9 +38,9 @@ const Login = () => {
throw new Error(result.message || 'Login failed');
}
// Handle successful login (e.g., store token, redirect)
Cookies.set('authToken',result.token,{
expire:'1h',
secure:true
Cookies.set('authToken', result.token, {
expire: '1h',
secure: true,
});
message.success('Login successful');
navigate('/');
Expand Down Expand Up @@ -83,17 +82,20 @@ const Login = () => {
className="input w-full h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[15px] font-semibold text-[#323232] p-2.5 focus:outline-none focus:border-[#2d8cf0] placeholder-[#666] placeholder-opacity-80"
name="password"
placeholder="Password"
type={hidden ? "password" : "text"}
type={hidden ? 'password' : 'text'}
onChange={(e) => handleChange(e)}
/>
<button className="absolute top-1/2 -translate-y-1/2 right-4" onClick={(e)=>{
e.preventDefault();
setHidden(!hidden)
}}>
{hidden ? <FaEyeSlash/> : <FaEye/>}
<button
className="absolute top-1/2 -translate-y-1/2 right-4"
onClick={(e) => {
e.preventDefault();
setHidden(!hidden);
}}
>
{hidden ? <FaEyeSlash /> : <FaEye />}
</button>
</div>

<div className="transform hover:text-red-500 transition">
<Link to={'/email-verify'}>Forgot Password?</Link>
</div>
Expand All @@ -104,10 +106,21 @@ const Login = () => {
<Link to={'/signup'}>Register Here</Link>
</span>
</h3>
<a
href="http://localhost:3000/api/user/auth/google"
className="text-[#666] font-semibold text-xl transform hover:scale-110 hover:-translate-y-1 hover:text-green-500 transition w-full"
>
<button
type="button"
className="button-confirm px-4 w-full h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[17px] font-semibold text-[#323232] cursor-pointer active:shadow-none active:translate-x-[3px] active:translate-y-[3px]"
>
Sign in with Google
</button>
</a>
{error && <p className="text-red-500 mt-2">{error}</p>}
<button
type="submit"
className="button-confirm mx-auto mt-12 px-4 w-30 h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[17px] font-semibold text-[#323232] cursor-pointer active:shadow-none active:translate-x-[3px] active:translate-y-[3px]"
className="button-confirm px-4 w-30 h-10 rounded-md border-2 border-black bg-beige shadow-[4px_4px_0px_0px_black] text-[17px] font-semibold text-[#323232] cursor-pointer active:shadow-none active:translate-x-[3px] active:translate-y-[3px]"
>
{isLoading ? 'Loading...' : 'Let’s Log you in →'}
</button>
Expand Down
Loading

0 comments on commit 21432b1

Please sign in to comment.