fallback sign in flow
This commit is contained in:
@@ -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)
|
||||||
|
try {
|
||||||
await signInWithPopup(auth, googleProvider)
|
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,
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user