Skip to content

Commit a013b18

Browse files
committed
fix: harden google auth flow and prevent false-success navigation
1 parent 02c46c6 commit a013b18

3 files changed

Lines changed: 105 additions & 49 deletions

File tree

app/src/Context/AuthContext.jsx

Lines changed: 94 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,34 @@ export const useAuth = () => {
1515
};
1616
const googleProvider = new GoogleAuthProvider();
1717
const BACKEND = import.meta.env.VITE_BACKEND;
18+
const parseStoredJSON = (key) => {
19+
const rawValue = localStorage.getItem(key);
20+
if (!rawValue) return null;
21+
try {
22+
return JSON.parse(rawValue);
23+
} catch {
24+
localStorage.removeItem(key);
25+
return null;
26+
}
27+
};
28+
29+
const readJsonSafely = async (response) => {
30+
const contentType = response.headers.get("content-type") || "";
31+
if (!contentType.toLowerCase().includes("application/json")) {
32+
return null;
33+
}
34+
try {
35+
return await response.json();
36+
} catch {
37+
return null;
38+
}
39+
};
1840

1941
export default AuthContext;
2042

2143
export const AuthProvider = ({ children }) => {
2244
let [authTokens, setAuthTokens] = useState(
23-
localStorage.getItem("authTokens")
24-
? JSON.parse(localStorage.getItem("authTokens"))
25-
: null,
45+
parseStoredJSON("authTokens"),
2646
);
2747
let [user, setUser] = useState(
2848
authTokens ? jwtDecode(authTokens.access) : null,
@@ -32,35 +52,39 @@ export const AuthProvider = ({ children }) => {
3252

3353
const isAuthenticated = Boolean(authTokens?.access);
3454
let [userNames, setUserNames] = useState(
35-
localStorage.getItem("userNames")
36-
? JSON.parse(localStorage.getItem("userNames"))
37-
: null,
55+
parseStoredJSON("userNames"),
3856
);
3957
useEffect(() => {
40-
if (authTokens) {
41-
setUser(jwtDecode(authTokens.access));
42-
} else {
43-
setUser(null);
44-
}
45-
setLoading(false);
46-
}, [authTokens]);
58+
if (authTokens) {
59+
setUser(jwtDecode(authTokens.access));
60+
} else {
61+
setUser(null);
62+
}
63+
setLoading(false);
64+
}, [authTokens]);
4765

4866

4967
let getUsernamesData = async (authToken) => {
50-
let usernames_response = await fetch(BACKEND + "/userDetails/", {
51-
method: "GET",
52-
headers: {
53-
"Content-Type": "application/json",
54-
Authorization: "Bearer " + authToken.access,
55-
},
56-
});
57-
let usernames_data = await usernames_response.json();
58-
if (usernames_response.status === 200) {
59-
localStorage.setItem("userNames", JSON.stringify(usernames_data));
60-
} else {
61-
console.log("ERROR!!!");
68+
if (!authToken?.access) return null;
69+
try {
70+
let usernames_response = await fetch(BACKEND + "/userDetails/", {
71+
method: "GET",
72+
headers: {
73+
"Content-Type": "application/json",
74+
Authorization: "Bearer " + authToken.access,
75+
},
76+
});
77+
let usernames_data = await readJsonSafely(usernames_response);
78+
if (usernames_response.status === 200 && usernames_data) {
79+
localStorage.setItem("userNames", JSON.stringify(usernames_data));
80+
return usernames_data;
81+
}
82+
localStorage.removeItem("userNames");
83+
return null;
84+
} catch {
85+
localStorage.removeItem("userNames");
86+
return null;
6287
}
63-
return usernames_data;
6488
};
6589
let loginUser = async (form_data) => {
6690
let response = await fetch(BACKEND + "/api/token/", {
@@ -73,8 +97,8 @@ export const AuthProvider = ({ children }) => {
7397
password: form_data.password,
7498
}),
7599
});
76-
let data = await response.json();
77-
if (response.status === 200) {
100+
let data = await readJsonSafely(response);
101+
if (response.status === 200 && data?.access) {
78102
setAuthTokens(data);
79103
setUser(jwtDecode(data.access));
80104
localStorage.setItem("authTokens", JSON.stringify(data));
@@ -124,8 +148,8 @@ export const AuthProvider = ({ children }) => {
124148
password: form_data.password,
125149
}),
126150
});
127-
let data = await response.json();
128-
if (response.status === 200) {
151+
let data = await readJsonSafely(response);
152+
if (response.status === 200 && data?.access) {
129153
setAuthTokens(data);
130154
setUser(jwtDecode(data.access));
131155
localStorage.setItem("authTokens", JSON.stringify(data));
@@ -171,70 +195,97 @@ export const AuthProvider = ({ children }) => {
171195
const SignInWithGoogle = async () => {
172196
let response;
173197
try {
198+
if (!auth) {
199+
alert("Firebase is not configured. Check frontend env values.");
200+
return false;
201+
}
174202
response = await signInWithPopup(auth, googleProvider);
175203
if (response && !(response["status"] === 400)) {
204+
const credential = GoogleAuthProvider.credentialFromResult(response);
205+
const accessToken =
206+
credential?.accessToken || response?.user?.accessToken;
207+
if (!accessToken) {
208+
alert("Google login failed: missing access token.");
209+
return false;
210+
}
176211
let logresponse = await fetch(BACKEND + "/api/token/google/", {
177212
method: "POST",
178213
headers: {
179214
"Content-Type": "application/json",
180215
},
181216
body: JSON.stringify({
182-
token: response.user.accessToken,
217+
token: accessToken,
183218
}),
184219
});
185-
let data = await logresponse.json();
186-
if (logresponse.status === 200) {
220+
let data = await readJsonSafely(logresponse);
221+
if (logresponse.status === 200 && data?.token?.access) {
187222
let token = data.token;
188223
setAuthTokens(token);
189224
setUser(jwtDecode(token.access));
190225
localStorage.setItem("authTokens", JSON.stringify(token));
191226
let usernames_data = await getUsernamesData(token);
192227
setUserNames(usernames_data);
228+
return true;
193229
} else {
194-
alert(data.message);
230+
alert(data?.message || "Google login failed.");
231+
return false;
195232
}
196233
} else {
197-
console.log("Please try logging in again");
234+
return false;
198235
}
199236
} catch (error) {
200237
console.log(error);
201-
console.log("Please try logging in again");
238+
alert("Please try logging in again");
239+
return false;
202240
}
203-
return response;
204241
};
205242
const SignUpWithGoogle = async () => {
206243
let response;
207244
try {
245+
if (!auth) {
246+
alert("Firebase is not configured. Check frontend env values.");
247+
return false;
248+
}
208249
response = await signInWithPopup(auth, googleProvider);
209250
if (response && !(response["status"] === 400)) {
251+
const credential = GoogleAuthProvider.credentialFromResult(response);
252+
const accessToken =
253+
credential?.accessToken || response?.user?.accessToken;
254+
if (!accessToken) {
255+
alert("Google registration failed: missing access token.");
256+
return false;
257+
}
210258
let regresponse = await fetch(BACKEND + "/api/register/google/", {
211259
method: "POST",
212260
headers: {
213261
"Content-Type": "application/json",
214262
},
215263
body: JSON.stringify({
216-
token: response.user.accessToken,
264+
token: accessToken,
217265
username: response.user.email.split("@")[0],
218266
}),
219267
});
220-
let data = await regresponse.json();
221-
if (regresponse.status === 200) {
268+
let data = await readJsonSafely(regresponse);
269+
if (regresponse.status === 200 && data?.token?.access) {
222270
let token = data.token;
223271
setAuthTokens(token);
224272
setUser(jwtDecode(token.access));
225273
localStorage.setItem("authTokens", JSON.stringify(token));
274+
let usernames_data = await getUsernamesData(token);
275+
setUserNames(usernames_data);
276+
return true;
226277
} else {
227278
alert("Please Try registering again");
279+
return false;
228280
}
229-
console.log(response);
230281
} else {
231-
alert("Please Try registering again");
282+
return false;
232283
}
233284
} catch (error) {
234285
console.log(error);
235286
alert("Please Try registering again");
287+
return false;
236288
}
237-
return response;
238289
};
239290
let contextData = {
240291
user: user,

app/src/components/Login.jsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,12 @@ const Login = () => {
4747

4848
async function handleGoogleAuth(e) {
4949
e.preventDefault();
50-
await SignInWithGoogle();
51-
navigate("/");
52-
}
50+
const success = await SignInWithGoogle();
51+
if (success) {
52+
navigate("/");
53+
}
54+
}
55+
5356
if (loading) {
5457
return (
5558
<div
@@ -130,4 +133,4 @@ const Login = () => {
130133
</div>
131134
);
132135
};
133-
export default Login;
136+
export default Login;

app/src/components/Register.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ const Register = () => {
5757

5858
const handleGoogleRegister = async (e) => {
5959
e.preventDefault();
60-
await SignUpWithGoogle();
61-
navigate("/profile");
60+
const success = await SignUpWithGoogle();
61+
if (success) {
62+
navigate("/profile");
63+
}
6264
};
6365
return (
6466
<div

0 commit comments

Comments
 (0)