-
Notifications
You must be signed in to change notification settings - Fork 80
fix(ios): recover session from biometric Keychain when cookies are missing #32150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,8 @@ import { | |
| import { syncOnboardingUser } from "@/domains/onboarding/prefs.js"; | ||
| import { clearOrganization } from "@/stores/organization-store.js"; | ||
| import { useEventBusStore } from "@/stores/event-bus-store.js"; | ||
| import { isNativePlatform, installSessionCookies } from "@/runtime/native-auth.js"; | ||
| import { isBiometricEnabled, retrieveBiometricToken } from "@/runtime/native-biometric.js"; | ||
|
|
||
| export interface AuthUser { | ||
| id: string | null; | ||
|
|
@@ -107,6 +109,27 @@ const useAuthStoreBase = create<AuthStore>()((set) => ({ | |
| } catch (err) { | ||
| console.error("auth.initSession failed", err); | ||
| } | ||
|
|
||
| // Biometric recovery: on iOS, the session cookie may have been lost | ||
| // when WKWebView was killed. Try to restore from Keychain via Face ID. | ||
| if (isNativePlatform() && isBiometricEnabled()) { | ||
| try { | ||
| const token = await retrieveBiometricToken(); | ||
| if (token) { | ||
| installSessionCookies(token); | ||
| const retryResult = await getSession(); | ||
| if (retryResult.ok && retryResult.data.user) { | ||
|
Comment on lines
+119
to
+121
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
After writing the recovered token with Useful? React with 👍 / 👎. |
||
| const user = toAuthUser(retryResult.data.user); | ||
| syncUserScopedState(user?.id ?? null); | ||
| set({ isLoggedIn: true, isLoading: false, user }); | ||
| return; | ||
| } | ||
| } | ||
| } catch (err) { | ||
| console.warn("auth.initSession biometric recovery failed", err); | ||
| } | ||
| } | ||
|
|
||
| syncUserScopedState(null); | ||
| set({ isLoggedIn: false, isLoading: false, user: null }); | ||
| }, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The biometric branch runs for every initial session miss, including transient network errors or server 5xx responses from
getSession(), not just missing/expired auth cookies. On native devices with biometrics enabled, this can trigger unnecessary Face ID/Touch ID prompts during outages or offline resumes, even though recovery cannot succeed in those conditions.Useful? React with 👍 / 👎.