diff --git a/frontend/src/components/auth/SocialAuth.jsx b/frontend/src/components/auth/SocialAuth.jsx index 6d6fc1c..a319c07 100644 --- a/frontend/src/components/auth/SocialAuth.jsx +++ b/frontend/src/components/auth/SocialAuth.jsx @@ -17,13 +17,20 @@ const GITHUB_ICON = ( ); export default function SocialAuth() { - const { loginWithProvider, error: authError } = useAuth(); + const { loginWithProvider } = useAuth(); const [loadingProvider, setLoadingProvider] = useState(null); + const [error, setError] = useState(null); async function handleProviderLogin(providerName) { + setError(null); setLoadingProvider(providerName); - await loginWithProvider(providerName); - // Page navigates away on redirect — loading state clears on return + try { + await loginWithProvider(providerName); + } catch (err) { + setError(err.message); + } finally { + setLoadingProvider(null); + } } return ( @@ -34,8 +41,8 @@ export default function SocialAuth() {
- {authError && ( -

{authError}

+ {error && ( +

{error}

)}
diff --git a/frontend/src/context/AuthContext.jsx b/frontend/src/context/AuthContext.jsx index e1b2824..01aeb7d 100644 --- a/frontend/src/context/AuthContext.jsx +++ b/frontend/src/context/AuthContext.jsx @@ -1,5 +1,5 @@ import { createContext, useContext, useReducer, useCallback, useEffect } from 'react'; -import { signInWithRedirect, getRedirectResult, signOut as firebaseSignOut } from 'firebase/auth'; +import { signInWithPopup, signOut as firebaseSignOut } from 'firebase/auth'; import { auth, providers } from '../config/firebase.js'; import { authApi } from '../lib/api'; @@ -34,32 +34,10 @@ export function AuthProvider({ children }) { useEffect(() => { const controller = new AbortController(); - - async function init() { - try { - const result = await getRedirectResult(auth); - if (result) { - const idToken = await result.user.getIdToken(); - const data = await authApi.oauthLogin(idToken); - dispatch({ type: 'AUTH_SUCCESS', payload: data.user }); - return; - } - } catch (err) { - let message = err.message; - if (err.code === 'auth/account-exists-with-different-credential') { - message = 'An account with this email already exists. Try signing in with a different provider.'; - } - dispatch({ type: 'AUTH_ERROR', payload: message }); - return; - } - - authApi - .me(controller.signal) - .then((data) => dispatch({ type: 'AUTH_SUCCESS', payload: data.user })) - .catch(() => dispatch({ type: 'LOGOUT' })); - } - - init(); + authApi + .me(controller.signal) + .then((data) => dispatch({ type: 'AUTH_SUCCESS', payload: data.user })) + .catch(() => dispatch({ type: 'LOGOUT' })); return () => controller.abort(); }, []); @@ -86,9 +64,18 @@ export function AuthProvider({ children }) { const loginWithProvider = useCallback(async (providerName) => { dispatch({ type: 'LOADING' }); try { - await signInWithRedirect(auth, providers[providerName]); + const result = await signInWithPopup(auth, providers[providerName]); + const idToken = await result.user.getIdToken(); + const data = await authApi.oauthLogin(idToken); + dispatch({ type: 'AUTH_SUCCESS', payload: data.user }); } catch (err) { - dispatch({ type: 'AUTH_ERROR', payload: err.message }); + await firebaseSignOut(auth).catch(() => {}); + let message = err.message; + if (err.code === 'auth/account-exists-with-different-credential') { + const other = providerName === 'google' ? 'GitHub' : 'Google'; + message = `An account with this email already exists. Try signing in with ${other} instead.`; + } + dispatch({ type: 'AUTH_ERROR', payload: message }); throw err; } }, []);