fallback sign in flow

This commit is contained in:
2026-03-26 15:05:03 +05:30
parent 625e4709d3
commit fa10677e41
2 changed files with 26 additions and 4 deletions

View File

@@ -10,6 +10,8 @@ import {
onAuthStateChanged, onAuthStateChanged,
setPersistence, setPersistence,
signInWithPopup, signInWithPopup,
signInWithRedirect,
getRedirectResult,
signOut as firebaseSignOut, signOut as firebaseSignOut,
type User, type User,
} from 'firebase/auth' } from 'firebase/auth'
@@ -43,6 +45,7 @@ type AuthContextValue = {
mongoUser: MongoUser | null mongoUser: MongoUser | null
loading: boolean loading: boolean
secretKey: Uint8Array | null secretKey: Uint8Array | null
authError: string | null
signInWithGoogle: () => Promise<void> signInWithGoogle: () => Promise<void>
signOut: () => Promise<void> signOut: () => Promise<void>
refreshMongoUser: () => Promise<void> refreshMongoUser: () => Promise<void>
@@ -56,6 +59,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
const [mongoUser, setMongoUser] = useState<MongoUser | null>(null) const [mongoUser, setMongoUser] = useState<MongoUser | null>(null)
const [secretKey, setSecretKey] = useState<Uint8Array | null>(null) const [secretKey, setSecretKey] = useState<Uint8Array | null>(null)
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
const [authError, setAuthError] = useState<string | null>(null)
// Initialize encryption keys on login // Initialize encryption keys on login
async function initializeEncryption(authUser: User) { async function initializeEncryption(authUser: User) {
@@ -151,6 +155,12 @@ export function AuthProvider({ children }: { children: ReactNode }) {
} }
useEffect(() => { useEffect(() => {
// Handle returning from a redirect sign-in (mobile flow)
getRedirectResult(auth).catch((error) => {
console.error('[Auth] Redirect sign-in error:', error)
setAuthError(error instanceof Error ? error.message : 'Sign-in failed')
})
const unsubscribe = onAuthStateChanged(auth, async (u) => { const unsubscribe = onAuthStateChanged(auth, async (u) => {
setUser(u) setUser(u)
if (u) { if (u) {
@@ -170,8 +180,19 @@ export function AuthProvider({ children }: { children: ReactNode }) {
}, []) }, [])
async function signInWithGoogle() { async function signInWithGoogle() {
setAuthError(null)
await setPersistence(auth, browserLocalPersistence) await setPersistence(auth, browserLocalPersistence)
await signInWithPopup(auth, googleProvider) try {
await signInWithPopup(auth, googleProvider)
} catch (err: unknown) {
const code = (err as { code?: string })?.code
if (code === 'auth/popup-blocked') {
// Popup was blocked (common on iOS Safari / Android WebViews) — fall back to redirect
await signInWithRedirect(auth, googleProvider)
} else {
throw err
}
}
} }
async function refreshMongoUser() { async function refreshMongoUser() {
@@ -205,6 +226,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
mongoUser, mongoUser,
secretKey, secretKey,
loading, loading,
authError,
signInWithGoogle, signInWithGoogle,
signOut, signOut,
refreshMongoUser, refreshMongoUser,

View File

@@ -5,7 +5,7 @@ import { GoogleSignInButton } from '../components/GoogleSignInButton'
import { TreeAnimation } from '../components/TreeAnimation' import { TreeAnimation } from '../components/TreeAnimation'
export default function LoginPage() { export default function LoginPage() {
const { user, loading, signInWithGoogle } = useAuth() const { user, loading, signInWithGoogle, authError } = useAuth()
const navigate = useNavigate() const navigate = useNavigate()
const [signingIn, setSigningIn] = useState(false) const [signingIn, setSigningIn] = useState(false)
const [error, setError] = useState<string | null>(null) const [error, setError] = useState<string | null>(null)
@@ -63,8 +63,8 @@ export default function LoginPage() {
<div className="lp__actions"> <div className="lp__actions">
<GoogleSignInButton loading={signingIn} onClick={handleGoogleSignIn} /> <GoogleSignInButton loading={signingIn} onClick={handleGoogleSignIn} />
<p className="lp__privacy">🔒 End-to-end encrypted. We never read your entries.</p> <p className="lp__privacy">🔒 End-to-end encrypted. We never read your entries.</p>
{error && ( {(error || authError) && (
<p className="lp__error" role="alert">{error}</p> <p className="lp__error" role="alert">{error || authError}</p>
)} )}
</div> </div>
</div> </div>