Skip to content

Commit

Permalink
Merge pull request #3 from ShaunDaniel/JWT-Auth
Browse files Browse the repository at this point in the history
Added JWT to authorization header
  • Loading branch information
ShaunDaniel committed Mar 31, 2024
2 parents 7cb7486 + ee05f28 commit cad8a3c
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 129 deletions.
2 changes: 1 addition & 1 deletion backend/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const session = require('express-session');
const mongoose = require('mongoose');
const passport = require('passport');
const useGoogleStrategy = require('./config/passport.config.js');
const useLocalStrategy = require('./config/passport.config.js');
// Routers
const userRouter = require("./routes/userRoutes");
const issueRouter = require("./routes/issueRoutes");
Expand All @@ -29,6 +28,7 @@ app.use(cors({
origin: function(origin, callback){
if(!origin) return callback(null, true);
if(allowedOrigins.indexOf(origin) === -1){
console.log(origin);
var msg = 'The CORS policy for this site does not ' +
'allow access from the specified Origin.';
return callback(new Error(msg), false);
Expand Down
33 changes: 12 additions & 21 deletions backend/src/config/passport.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,29 @@ const User = require('../models/user');

const GoogleStrategy = passportGoogle.Strategy;
function useGoogleStrategy(){
passport.use(new GoogleStrategy
({
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID || '',
clientSecret: process.env.GOOGLE_CLIENT_SECRET || '',
callbackURL: '/v1/auth/google/callback',

}, (accessToken, refreshToken, profile, done) => {
try {
if (!profile._json.email) throw "User does not have email";
User.findOne({ email: profile._json.email }).then((user) => {

if (user) {
done(null, user);
User.findOne({ email: profile._json.email }).then((currentUser) => {
if (currentUser) {
done(null, currentUser);
} else {
const newUser = new User({
username: profile._json.name,
new User({
googleId: profile.id,
firstName: profile.name.givenName,
lastName: profile.name.familyName,
email: profile._json.email,
city: '-',
state_name: '-',
password: '-',
googleId: profile._json.sub,
firstName: profile._json.given_name,
lastName: profile._json.family_name,
}).save().then((newUser) => {
done(null, newUser);
});
newUser.save()
.then((user) => {
done(null, user);
})
.catch((err) => {
done(err);
});
}


});
} catch (err) {
console.error(err);
Expand Down
30 changes: 24 additions & 6 deletions backend/src/middlewares/isAuthenticated.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
function isAuthenticated(req, res, next) {
if (req.user) {return next();}
}


module.exports = isAuthenticated;
function authenticateToken(req, res, next) {
// Get auth header value
const bearerHeader = req.headers['authorization'];
// Check if bearer is undefined
if(typeof bearerHeader !== 'undefined') {
// Split at the space
const bearer = bearerHeader.split(' ');
// Get token from array
const bearerToken = bearer[1];
// Verify the token
jwt.verify(bearerToken, process.env.JWT_SECRET, (err, authData) => {
if(err) {
res.sendStatus(403);
} else {
// If verification is successful, attach the user data to the request
req.user = authData;
next();
}
});
} else {
// Forbidden
res.sendStatus(403);
}
}
4 changes: 2 additions & 2 deletions backend/src/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const userSchema = new mongoose.Schema({
lastName: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String},
city: { type: String, required: true },
state_name: { type: String, required: true },
city: { type: String, required: true,default: '-'},
state_name: { type: String, required: true,default: '-'},
googleId: { type: String, required: false },
});

Expand Down
4 changes: 1 addition & 3 deletions backend/src/routes/auth.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
const express = require('express');
const Router = require('express').Router;
const passport = require('passport');
const jwt = require('jsonwebtoken');
const dotenv = require('dotenv').config();

var authRouter = express.Router();

Expand All @@ -14,7 +12,7 @@ authRouter.get('/google/callback',passport.authenticate('google', { failureRedir
process.env.JWT_SECRET,
{ expiresIn: "1h" },
);
res.redirect(`${process.env.FRONTEND_URL}?token=${token}`);
res.redirect(`${process.env.FRONTEND_URL}/?token=${token}`);
}
);

Expand Down
84 changes: 61 additions & 23 deletions backend/src/routes/userRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,24 @@ const isAuthenticated = require("../middlewares/isAuthenticated");
const jwt = require('jsonwebtoken');
const router = express.Router();

router.post("/user-details", (req, res) => {
router.get("/user-details", (req, res) => {
console.log("Inside user-details");
console.log(req.body);
if(req.body.jwtToken){
const decoded = jwt.verify(req.body.jwtToken, process.env.JWT_SECRET || '');
res.json(decoded);
const authHeader = req.headers['authorization'];
console.log(authHeader)
if (authHeader) {
const token = authHeader.split(' ')[1]; // Bearer <token>
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
res.status(401).json({ message: "Invalid token" });
} else {
console.log(decoded);
res.json(decoded);
}
});
} else {
res.status(404).json({ message: "User not found" });
res.status(401).json({ message: "Token not found" });
}
});

router.get("/email-exists/:email", (req, res) => {
const { email } = req.params;
User.findOne({ email })
Expand Down Expand Up @@ -55,13 +62,10 @@ router.post("/login", async (req, res) => {
googleId: user.googleId,
},
};
jwt.sign(
payload,
process.env.JWT_SECRET,
{ expiresIn: 3600 }, // token expires in 1 hour
jwt.sign(payload,process.env.JWT_SECRET,{ expiresIn: 3600 },
(err, token) => {
if (err) throw err;
res.json({ token });
res.status(200).json({jwtToken: `Bearer ${token}`});
}
);

Expand All @@ -78,26 +82,60 @@ router.post("/login", async (req, res) => {
// Register route
router.post("/register", (req, res) => {
console.log("Inside register");

console.log(req.body);
User.findOne({ email: req.body.email }).then((user) => {
console.log("Checking user",user)
if (user) {
User.updateOne({ email: req.body.email,city: req.body.city,state_name:req.body.state_name }, { $set: req.body })
.then((user) => {
console.log("User updated successfully");
console.log(user)
res.status(201).send(req.body);
})
.catch((err) => {
if(user.googleId){
User.updateOne({ email: req.body.email }, req.body).then((user) => {
const token = jwt.sign(
{ user: req.body },
process.env.JWT_SECRET,
{ expiresIn: "1h" },
);
res.status(201).json({jwtToken: `Bearer ${token}`});
}
).catch((err) => {
res.status(400).json(err);
});
return;
}
else{
res.status(400).json({ message: "User already exists" });
}
} else {
const user = new User(req.body);
user
.save()
.then((user) => {
res.status(201).send(user);
console.log("Google User Registered for the first time",user)
const token = jwt.sign(
{ user: user },
process.env.JWT_SECRET,
{ expiresIn: "1h" },
);
res.status(201).json({jwtToken: `Bearer ${token}`});function authenticateToken(req, res, next) {
// Get auth header value
const bearerHeader = req.headers['authorization'];
// Check if bearer is undefined
if(typeof bearerHeader !== 'undefined') {
// Split at the space
const bearer = bearerHeader.split(' ');
// Get token from array
const bearerToken = bearer[1];
// Verify the token
jwt.verify(bearerToken, process.env.JWT_SECRET, (err, authData) => {
if(err) {
res.sendStatus(403);
} else {
// If verification is successful, attach the user data to the request
req.user = authData;
next();
}
});
} else {
// Forbidden
res.sendStatus(403);
}
}
})
.catch((err) => {
res.status(400).json(err);
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import UserContext from './components/UserContext';

function App() {

const [user, setUser] = useState();

const [user, setUser] = useState(null);

useEffect(() => {
const jwtToken = localStorage.getItem("jwtToken");
if (jwtToken) {
console.log("Inside user_details",jwtToken);
userService.user_details(jwtToken)
.then((res) => {
setUser(res.data.user);
Expand All @@ -35,7 +36,7 @@ function App() {

return (
<UserContext.Provider value={{ user, setUser }}>
<ChakraProvider theme={theme}>
<ChakraProvider theme={theme}>
<Navbar/>
<Routes>
<Route path="/" element={<Homepage/>} />
Expand All @@ -44,10 +45,9 @@ function App() {
<Route path="/register/2" element={<FinishRegister/>} />
</Routes>
<Footer/>
</ChakraProvider>
</ChakraProvider>
</UserContext.Provider>
);
}


export default App;
export default App;
5 changes: 3 additions & 2 deletions frontend/src/components/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ function Login() {
if (res.status !== 401 && res.status !== 500) {
navigate('/');
window.location.reload();
localStorage.setItem('jwtToken', res.data.token); // set JWT token to local storage
setIsLoading(false);

localStorage.setItem('jwtToken', `${res.data.jwtToken}`);

setIsFormError(false);
} else{
setIsLoading(false);
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/Logout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ function Logout() {


const handleLogout = () => {
// Clear the JWT token from the local storage

localStorage.removeItem('jwtToken');

navigate('/');
window.location.reload();
};
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/components/Nav.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { Box, Text, Flex } from '@chakra-ui/react'
import React from 'react'
import Logout from './Logout.jsx'
import { useEffect, useState,useContext} from 'react'
import { useLocation, useNavigate } from 'react-router-dom';
import { useEffect,useContext} from 'react'
import { useNavigate } from 'react-router-dom';
import UserContext from './UserContext.jsx';
import userService from '../services/userService.js';

function Nav() {


const {user,setUser} = useContext(UserContext);
const navigate = useNavigate();
userService.user_details().then((res)=>{console.log(res)}).catch((err)=>{console.log(err)})


return (
<Box bgColor={'#222831'} h={"10vh"}>
Expand Down
Loading

0 comments on commit cad8a3c

Please sign in to comment.