Skip to content

Commit 8857a97

Browse files
authored
Merge pull request #87 from anshul23102/fix/80-move-gh-token-out-of-session-storage
fix(security): move GitHub OAuth access token from sessionStorage to React state
2 parents e19a60b + 90c2294 commit 8857a97

1 file changed

Lines changed: 15 additions & 7 deletions

File tree

src/context/AuthContext.jsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ export const AuthProvider = ({ children }) => {
2222
const [userData, setUserData] = useState(null);
2323
const [loading, setLoading] = useState(true);
2424
const [isOnboarding, setIsOnboarding] = useState(false);
25+
// GitHub OAuth access token kept in React state only -- never written to
26+
// sessionStorage or localStorage. Storing it in Web Storage exposes it to
27+
// any JavaScript running on the page (XSS). Keeping it in memory means it
28+
// is lost on page refresh, but the token is only needed once after login
29+
// to call fetchGitHubStats, so this trade-off is acceptable.
30+
const [ghAccessToken, setGhAccessToken] = useState(null);
2531

2632
// Listen to Auth State Changed
2733
useEffect(() => {
@@ -92,8 +98,8 @@ export const AuthProvider = ({ children }) => {
9298
const githubId = additionalInfo?.profile?.id || null;
9399
const avatar = additionalInfo?.profile?.avatar_url || authUser.photoURL || "";
94100

95-
// Store GitHub accessToken in sessionStorage securely (non-persistent across tabs for security)
96-
sessionStorage.setItem(`gh_token_${authUser.uid}`, accessToken);
101+
// Keep the token in React state only -- do not write to Web Storage.
102+
setGhAccessToken(accessToken);
97103

98104
const userDocRef = doc(db, "users", authUser.uid);
99105
const docSnap = await getDoc(userDocRef);
@@ -146,23 +152,25 @@ export const AuthProvider = ({ children }) => {
146152
const logout = async () => {
147153
setLoading(true);
148154
try {
149-
if (user) {
150-
sessionStorage.removeItem(`gh_token_${user.uid}`);
151-
}
152155
await signOutUser();
153156
setUser(null);
154157
setUserData(null);
155158
setIsOnboarding(false);
159+
setGhAccessToken(null);
156160
} catch (error) {
157161
console.error("Logout failure:", error);
158162
} finally {
159163
setLoading(false);
160164
}
161165
};
162166

163-
// Securely fetches GitHub stats on the client once using the transient OAuth token
167+
// Fetches GitHub stats once after login using the in-memory OAuth token.
168+
// The token is no longer read from sessionStorage -- it comes from the
169+
// ghAccessToken state variable which is populated on login and cleared on
170+
// logout. This prevents any JavaScript on the page from reading the token
171+
// via sessionStorage.getItem().
164172
const fetchGitHubStats = async (uid, username) => {
165-
const token = sessionStorage.getItem(`gh_token_${uid}`);
173+
const token = ghAccessToken;
166174
const headers = token ? { Authorization: `token ${token}` } : {};
167175

168176
try {

0 commit comments

Comments
 (0)