Skip to content
Merged
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
28 changes: 12 additions & 16 deletions src/context/AuthContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,9 @@ export const AuthProvider = ({ children }) => {
const [userData, setUserData] = useState(null);
const [loading, setLoading] = useState(true);
const [isOnboarding, setIsOnboarding] = useState(false);
// GitHub OAuth access token persisted in sessionStorage to survive page refreshes
const [ghAccessToken, setGhAccessToken] = useState(() => {
return sessionStorage.getItem("gh_access_token") || null;
});
// GitHub OAuth access token stored only in memory, not persisted to storage
// Firebase Auth handles session persistence securely via HTTP-only cookies
const [ghAccessToken, setGhAccessToken] = useState(null);

useEffect(() => {
let unsubscribeSnapshot = null;
Expand All @@ -85,11 +84,10 @@ export const AuthProvider = ({ children }) => {

if (currentUser) {
setUser(currentUser);
const token = sessionStorage.getItem(`gh_token_${currentUser.uid}`) || sessionStorage.getItem("gh_access_token");
if (token) {
setGhAccessToken(token);
}

// Token is only available during the current session in memory
// It will be null on page refresh, requiring fresh authentication
// This is the secure default behavior

const userDocRef = doc(db, "users", currentUser.uid);

unsubscribeSnapshot = onSnapshot(userDocRef, (docSnap) => {
Expand Down Expand Up @@ -133,9 +131,9 @@ export const AuthProvider = ({ children }) => {
const githubId = additionalInfo?.profile?.id || null;
const avatar = additionalInfo?.profile?.avatar_url || authUser.photoURL || "";

// Save the token to sessionStorage and state to keep user authenticated across refreshes
sessionStorage.setItem("gh_access_token", accessToken);
sessionStorage.setItem(`gh_token_${authUser.uid}`, accessToken);
// Store token only in memory for current session
// Firebase Auth handles persistent session via secure HTTP-only cookies
// Token is not persisted to localStorage or sessionStorage to prevent XSS theft
setGhAccessToken(accessToken);

const userDocRef = doc(db, "users", authUser.uid);
Expand Down Expand Up @@ -184,10 +182,8 @@ export const AuthProvider = ({ children }) => {
const logout = async () => {
setLoading(true);
try {
if (user) {
sessionStorage.removeItem(`gh_token_${user.uid}`);
}
sessionStorage.removeItem("gh_access_token");
// No need to remove from storage since token is only in memory
// Firebase Auth session will be cleared by signOutUser()
await signOutUser();
setUser(null);
setUserData(null);
Expand Down