Skip to content

Oauth Integration Successfully - #83

Open
alfishahrin-05 wants to merge 12 commits into
mainfrom
sprint-2
Open

Oauth Integration Successfully#83
alfishahrin-05 wants to merge 12 commits into
mainfrom
sprint-2

Conversation

@alfishahrin-05

Copy link
Copy Markdown
Collaborator

No description provided.

Copilot AI review requested due to automatic review settings January 31, 2026 18:15
@alfishahrin-05

Copy link
Copy Markdown
Collaborator Author

@copilot

Copilot AI commented Jan 31, 2026

Copy link
Copy Markdown

@alfishahrin-05 I've opened a new pull request, #84, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements Google OAuth 2.0 integration for the Odyssey travel planning application. The implementation adds alternative authentication via Google while maintaining the existing manual username/password authentication system.

Changes:

  • Added Google OAuth authentication using Passport.js strategy
  • Enhanced User model to support multiple authentication methods (manual/OAuth)
  • Implemented profile settings page with preference management
  • Updated UI components with new dashboard and styling improvements
  • Added session management with express-session for OAuth flow

Reviewed changes

Copilot reviewed 23 out of 30 changed files in this pull request and generated 19 comments.

Show a summary per file
File Description
server/src/config/passport.js New Passport Google OAuth strategy configuration
server/src/routes/oauth.js New OAuth routes for Google authentication flow
server/src/server.js Integrated session middleware and OAuth routes
server/src/models/User.js Added OAuth fields and made password optional for OAuth users
server/src/middleware/authMiddleware.js Enhanced JWT verification with better error handling
server/src/routes/protected.js Added profile update endpoint
server/src/routes/auth.js Added logging for login operations
client/odyssey/app/login/page.tsx Added Google sign-in button
client/odyssey/app/signup/page.tsx Added Google sign-up button
client/odyssey/app/dashboard/page.tsx OAuth callback handling and UI redesign
client/odyssey/app/profile/page.tsx Complete profile management implementation
client/odyssey/app/layout.tsx Added font imports for UI consistency
server/package.json Added passport, express-session dependencies
client/odyssey/package.json Removed @vis.gl/react-google-maps, updated React versions
Files not reviewed (6)
  • .idea/ProjectOdyssey.iml: Language not supported
  • .idea/modules.xml: Language not supported
  • .idea/vcs.xml: Language not supported
  • .idea/workspace.xml: Language not supported
  • client/odyssey/package-lock.json: Language not supported
  • server/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/src/server.js
// 5. Start Server
const PORT = process.env.PORT || 5001; // Defaults to 5001 if .env is missing
// 7. Start Server
const PORT = process.env.PORT || 4000; // Defaults to 4000 if .env is missing

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default PORT has been changed from 5001 to 4000. This is a breaking change that could affect existing deployments, documentation, and client configurations. Ensure this change is intentional and properly documented, or consider keeping backward compatibility.

Suggested change
const PORT = process.env.PORT || 4000; // Defaults to 4000 if .env is missing
const PORT = process.env.PORT || 5001; // Defaults to 5001 if .env is missing

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +41
// Redirect to frontend with token in query params
res.redirect(
`http://localhost:3000/dashboard?token=${encodeURIComponent(token)}&user=${encodeURIComponent(JSON.stringify(userData))}`
);

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security vulnerability: Passing sensitive JWT token in URL query parameters exposes it to browser history, server logs, and potential XSS attacks. Consider using HTTP-only cookies or POST request body instead for secure token transmission.

Suggested change
// Redirect to frontend with token in query params
res.redirect(
`http://localhost:3000/dashboard?token=${encodeURIComponent(token)}&user=${encodeURIComponent(JSON.stringify(userData))}`
);
// Set JWT in HTTP-only cookie and redirect to frontend without exposing the token in the URL
res.cookie("token", token, {
httpOnly: true,
secure: true,
sameSite: "lax",
maxAge: 60 * 60 * 1000, // 1 hour in milliseconds, matching JWT expiry
});
res.redirect("http://localhost:3000/dashboard");

Copilot uses AI. Check for mistakes.
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "http://localhost:4000/api/auth/google/callback",

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded callback URL with localhost will not work in production. This should be configurable via environment variable (e.g., process.env.BACKEND_URL) to support different deployment environments.

Copilot uses AI. Check for mistakes.
Comment on lines +193 to +195
onClick={() => {
window.location.href = "http://localhost:4000/api/auth/google";
}}

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded OAuth redirect URL with localhost will not work in production or when accessed from different devices. This should be configurable via environment variable.

Copilot uses AI. Check for mistakes.
Comment on lines +140 to +142
onClick={() => {
window.location.href = "http://localhost:4000/api/auth/google";
}}

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded OAuth redirect URL with localhost will not work in production or when accessed from different devices. This should be configurable via environment variable.

Copilot uses AI. Check for mistakes.
Comment thread server/src/models/User.js
// Hash password before saving
// Hash password before saving (only for manual auth)
userSchema.pre("save", async function() {
if (!this.isModified("password")) return;

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The password hashing middleware will fail for OAuth users who don't have a password field. Add a check to only hash the password if it exists: if (!this.isModified("password") || !this.password) return;

Suggested change
if (!this.isModified("password")) return;
if (!this.isModified("password") || !this.password) return;

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +72
// OAuth callback - store token and user
localStorage.setItem("token", tokenFromUrl);
if (userFromUrl) {
localStorage.setItem("user", userFromUrl);
}
// Clean URL
router.replace("/dashboard");

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security risk: The OAuth callback stores tokens and user data directly from URL parameters without validation. An attacker could craft a malicious URL with fake tokens. Add server-side token validation before storing in localStorage, or use a more secure callback mechanism.

Suggested change
// OAuth callback - store token and user
localStorage.setItem("token", tokenFromUrl);
if (userFromUrl) {
localStorage.setItem("user", userFromUrl);
}
// Clean URL
router.replace("/dashboard");
try {
// Validate the token from URL with the backend before storing
const res = await fetch("http://localhost:4000/api/user/profile", {
method: "GET",
headers: {
"Authorization": `Bearer ${tokenFromUrl}`,
"Content-Type": "application/json",
},
});
if (!res.ok) {
const errorData = await res.json();
console.error("Backend error (OAuth callback):", errorData);
throw new Error(errorData.message || "Invalid token");
}
const data = await res.json();
// Token is valid - persist it and associated user data
localStorage.setItem("token", tokenFromUrl);
if (data.user) {
localStorage.setItem("user", JSON.stringify(data.user));
} else if (userFromUrl) {
// Fallback: only use userFromUrl if backend returned no user,
// but do not trust it over backend data.
localStorage.setItem("user", userFromUrl);
}
setUser(data.user ?? null);
// Clean URL
router.replace("/dashboard");
} catch (err: any) {
console.error("Error validating OAuth token from URL:", err);
localStorage.removeItem("token");
localStorage.removeItem("user");
router.push("/login");
} finally {
setLoading(false);
}

Copilot uses AI. Check for mistakes.
const [user, setUser] = useState<any>(null);
const [loading, setLoading] = useState(true); // Add loading state
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); // State for mobile menu
const [loading, setLoading] = useState(true);

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable loading.

Suggested change
const [loading, setLoading] = useState(true);

Copilot uses AI. Check for mistakes.
"use client";

import React, { useState } from "react";
import React, { useState, useEffect } from "react";

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import useEffect.

Suggested change
import React, { useState, useEffect } from "react";
import React, { useState } from "react";

Copilot uses AI. Check for mistakes.

if (!res.ok) {
// Try to parse response as JSON, otherwise use raw text
let errorMessage = "Failed to save changes";

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initial value of errorMessage is unused, since it is always overwritten.

Suggested change
let errorMessage = "Failed to save changes";
let errorMessage: string;

Copilot uses AI. Check for mistakes.
Add OAuth integration for authentication
@alfishahrin-05

Copy link
Copy Markdown
Collaborator Author

@synced7x7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants