Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions GoogleAuth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Authentication (Google OAuth)

This project uses Google OAuth 2.0 for user authentication via @react-oauth/google.

```
Setup Required
1. Create Google OAuth Client
-> Go to Google Cloud Console:
(https://console.cloud.google.com/apis/credentials?utm_source=chatgpt.com)

-> Create OAuth Client ID
-> Choose Web application

2. Configure Authorized Origins
->Development
http://localhost:5173 (the port where your server is running i.e after running npm run dev)
->Production
https://your-domain.com (the deployed url, only imp when you want the app to go live (not for your local computer))
if working on local computer
the other javascript origin will be http://localhost

3. Configure Redirect URIs

->Development
http://localhost:5173
-> Production
https://your-domain.com (not necessary if you are not gonna deploy the app)

```

Environment Variables
Create a .env file in the root:

VITE_CLIENT_ID=your_google_client_id

⚠️ This is required for Google login to work.

``

Comment thread
Ridima28 marked this conversation as resolved.
That's it!
Google authentication will now work all fine !
16 changes: 2 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"private": true,
"version": "0.0.0",
"type": "module",

"scripts": {
"dev": "vite --host",
"build": "vite build",
Expand All @@ -14,17 +13,18 @@
"docker:dev": "docker compose --profile dev up --build",
"docker:prod": "docker compose --profile prod up -d --build"
},

"dependencies": {
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.15.6",
"@mui/material": "^5.15.6",
"@primer/octicons-react": "^19.25.0",
"@react-oauth/google": "^0.13.5",
"@vitejs/plugin-react": "^4.3.3",
"axios": "^1.7.7",
"express": "^5.2.1",
"framer-motion": "^12.23.12",
"jwt-decode": "^4.0.0",
"lucide-react": "^0.525.0",
"mongoose": "^9.6.2",
"octokit": "^4.0.2",
Expand All @@ -37,7 +37,6 @@
"recharts": "^3.8.1",
"tailwindcss": "^3.4.14"
},

"devDependencies": {
"@eslint/js": "^9.13.0",
"@testing-library/jest-dom": "^6.9.1",
Expand All @@ -49,33 +48,22 @@
"@types/react-dom": "^18.3.7",
"@types/react-redux": "^7.1.34",
"@types/react-router-dom": "^5.3.3",

"@vitejs/plugin-react-swc": "^3.5.0",

"autoprefixer": "^10.4.20",
"bcryptjs": "^3.0.3",

"eslint": "^9.13.0",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",

"express-session": "^1.18.2",

"globals": "^15.11.0",

"jasmine": "^5.13.0",
"jasmine-spec-reporter": "^7.0.0",

"jsdom": "^29.1.1",

"passport": "^0.7.0",
"passport-local": "^1.0.0",

"supertest": "^7.2.2",

"typescript-eslint": "^8.59.3",

"vite": "^5.4.10",
"vitest": "^4.1.6"
}
Expand Down
33 changes: 31 additions & 2 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,20 @@ const Navbar: React.FC = () => {
<NavLink to="/contributors" className={navLinkStyles}>
Contributors
</NavLink>

{localStorage.getItem("token") ? (
<button
onClick={() => {
localStorage.removeItem("token");
window.location.reload();
}}
className={navLinkStyles({ isActive: false })}>
Logout
</button>
) : (
<NavLink to="/login" className={navLinkStyles}>
Login
</NavLink>
)}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

{/* Theme Toggle */}
<button
Expand Down Expand Up @@ -130,7 +140,26 @@ const Navbar: React.FC = () => {
>
Contributors
</NavLink>

{localStorage.getItem("token") ? (
<button
onClick={() => {
localStorage.removeItem("token");
closeMenu();
window.location.reload();
}}
className={navLinkStyles({ isActive: false })}
>
Logout
</button>
) : (
<NavLink
to="/login"
className={navLinkStyles}
onClick={closeMenu}
>
Login
</NavLink>
)}
<NavLink
to="/login"
className={navLinkStyles}
Expand Down
7 changes: 6 additions & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@ import App from "./App.tsx";
import "./index.css";
import { BrowserRouter } from "react-router-dom";
import ThemeWrapper from "./context/ThemeContext.tsx";

import {GoogleOAuthProvider} from '@react-oauth/google';
const CLIENT_ID = import.meta.env.VITE_CLIENT_ID;
console.log("CLIENT_ID =", CLIENT_ID);
createRoot(document.getElementById("root")!).render(

<StrictMode>
<ThemeWrapper>
<BrowserRouter>
<GoogleOAuthProvider clientId = {CLIENT_ID}>
<App />
</GoogleOAuthProvider>
</BrowserRouter>
</ThemeWrapper>
</StrictMode>
Expand Down
24 changes: 22 additions & 2 deletions src/pages/Login/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import axios from "axios";
import { useNavigate, Link } from "react-router-dom";
import { ThemeContext } from "../../context/ThemeContext";
import type { ThemeContextType } from "../../context/ThemeContext";
import {jwtDecode} from "jwt-decode";
import { GoogleLogin} from "@react-oauth/google";

const backendUrl = import.meta.env.VITE_BACKEND_URL;

Expand All @@ -20,6 +22,7 @@ const Login: React.FC = () => {
const themeContext = useContext(ThemeContext) as ThemeContextType;
const { mode } = themeContext;


const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
Expand Down Expand Up @@ -106,6 +109,7 @@ const Login: React.FC = () => {
/>
</div>


<div className="relative">
<input
type="password"
Expand All @@ -122,7 +126,6 @@ const Login: React.FC = () => {
}`}
/>
</div>

<button
type="submit"
disabled={isLoading}
Expand All @@ -131,7 +134,24 @@ const Login: React.FC = () => {
{isLoading ? "Signing in..." : "Sign In"}
</button>
</form>

<div className="mt-10 flex justify-center ">
<GoogleLogin theme="outline" size="medium" shape= "pill" logo_alignment="center" width="10px"
onSuccess={async (credentialResponse) => {
const token = credentialResponse.credential;
if (!token) {
return;
}
try {
const res = await axios.post(`${backendUrl}/api/auth/google`, { credential: token });
+ localStorage.setItem("token", res.data.token);
+ navigate("/");
} catch (err) {
setMessage("Login failed. Please try again.");

}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}}
/>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
</div>
{/* Message */}
{message && (
<div className={`mt-6 p-4 rounded-2xl text-center text-sm font-medium ${
Expand Down