Skip to content

Commit 3e93551

Browse files
Google Auth Added (#677)
Co-authored-by: Kritika Singh <kritikasingh6881@gmail.com>
1 parent e223b8c commit 3e93551

File tree

13 files changed

+472
-59
lines changed

13 files changed

+472
-59
lines changed

.env.example

Lines changed: 0 additions & 4 deletions
This file was deleted.

login.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
1010
integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw=="
1111
crossorigin="anonymous" referrerpolicy="no-referrer">
12+
<!-- Google Identity Services -->
13+
<script src="https://accounts.google.com/gsi/client" async defer></script>
1214
</head>
1315
<body>
1416
<div class="container">
@@ -33,6 +35,19 @@ <h2>Login</h2>
3335
</div>
3436
<button type="submit">Login</button>
3537
</form>
38+
<div id="g_id_onload"
39+
data-client_id="164217635190-u5ajqhenmfp8j5erb0qr37r0kjj706pt.apps.googleusercontent.com"
40+
data-login_uri="http://localhost:5503/api/auth/google/callback"
41+
data-auto_prompt="false">
42+
</div>
43+
<div class="g_id_signin"
44+
data-type="standard"
45+
data-shape="rectangular"
46+
data-theme="outline"
47+
data-text="sign_in_with"
48+
data-size="large"
49+
data-logo_alignment="left">
50+
</div>
3651
<p class="form-link">Don't have an account? <a href="signup.html">Sign up</a></p>
3752
<p class="form-link"><a href="forgot-password.html">Forgot Password?</a></p>
3853
</div>

package-lock.json

Lines changed: 124 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"dependencies": {
3+
"express-session": "^1.18.2",
34
"nodemailer": "^7.0.5",
4-
"zod": "^4.1.3",
5-
"nodemailer": "^7.0.5"
5+
"zod": "^4.1.3"
66
}
77
}

scripts/auth.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
// Handle Google OAuth redirect with JWT token
2+
if (window.location.hash && window.location.hash.startsWith('#token=')) {
3+
const token = window.location.hash.substring(7) // Remove '#token='
4+
localStorage.setItem('token', token)
5+
// Clean up the URL
6+
window.history.replaceState(null, null, window.location.pathname)
7+
// Redirect to home or dashboard
8+
window.location.href = 'index.html'
9+
}
10+
111
const API = (() => {
212
const host = window.location.hostname
313
const base = (host === 'localhost' || host === '127.0.0.1')

server/config/passport.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const passport = require('passport');
2+
const GoogleStrategy = require('passport-google-oauth20').Strategy;
3+
const User = require('../models/User');
4+
require('dotenv').config()
5+
6+
console.log('GOOGLE_CLIENT_ID:', process.env.GOOGLE_CLIENT_ID);
7+
console.log('GOOGLE_CLIENT_SECRET:', process.env.GOOGLE_CLIENT_SECRET);
8+
9+
// Serialize user for session
10+
passport.serializeUser((user, done) => {
11+
done(null, user.id);
12+
});
13+
14+
// Deserialize user from session
15+
passport.deserializeUser(async (id, done) => {
16+
try {
17+
const user = await User.findById(id);
18+
done(null, user);
19+
} catch (err) {
20+
done(err, null);
21+
}
22+
});
23+
24+
// Google OAuth Strategy
25+
passport.use(new GoogleStrategy({
26+
clientID: process.env.GOOGLE_CLIENT_ID,
27+
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
28+
callbackURL: process.env.GOOGLE_REDIRECT_URI || 'http://localhost:5000/api/auth/google/callback'
29+
},
30+
async (accessToken, refreshToken, profile, done) => {
31+
try {
32+
// Check if user already exists with this Google ID
33+
let user = await User.findOne({ googleId: profile.id });
34+
35+
if (user) {
36+
return done(null, user);
37+
}
38+
39+
// Check if user exists with same email
40+
user = await User.findOne({ email: profile.emails[0].value });
41+
42+
if (user) {
43+
// Link Google account to existing user
44+
user.googleId = profile.id;
45+
await user.save();
46+
return done(null, user);
47+
}
48+
49+
// Create new user
50+
user = new User({
51+
username: profile.displayName.replace(/\s+/g, '').toLowerCase(), // Generate username from display name
52+
email: profile.emails[0].value,
53+
googleId: profile.id,
54+
// No password for Google users
55+
});
56+
57+
await user.save();
58+
done(null, user);
59+
} catch (err) {
60+
done(err, null);
61+
}
62+
}));
63+
64+
module.exports = passport;

server/models/User.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ const mongoose = require('mongoose')
33
const UserSchema = new mongoose.Schema({
44
username: { type: String, required: true },
55
email: { type: String, required: true, unique: true },
6-
password: { type: String, required: true }
6+
password: { type: String, required: true },
7+
googleId: { type: String, required: false, unique: true, sparse: true }
78
}, { timestamps: true })
89

910
module.exports = mongoose.model('User', UserSchema)

0 commit comments

Comments
 (0)