fix: awaitable logout() with always-settle timeout (both platforms) - #101
Closed
dianaKhortiuk-frontegg wants to merge 4 commits into
Closed
fix: awaitable logout() with always-settle timeout (both platforms)#101dianaKhortiuk-frontegg wants to merge 4 commits into
dianaKhortiuk-frontegg wants to merge 4 commits into
Conversation
…sion actually ends The bridge logout was fire-and-forget on both platforms: iOS called auth.logout() without the completion overload; Android ignored the SDK's callback parameter. JS had no way to know when the session was actually gone and relied solely on the auth-state event — which can be lost when logout coincides with app-level teardown, leaving the JS state authenticated forever and breaking the next login's state-transition detection (observed on-device). Both native SDKs already expose completion callbacks (iOS FronteggAuth.logout(_ completion:), Android logout(callback:)); the bridge just didn't use them. logout() now returns a Promise that resolves when the native SDK reports completion, and iOS pushes the final auth state to JS before resolving. The JS export is typed Promise<void>. Existing callers that ignore the return value are unaffected.
logout(promise) resolved only from the SDK completion callback, so `await logout()` would hang forever if that callback never fired. Add a 10s timeout fallback (parity with the iOS bridge) and an atomic compare-and-set guard so the promise resolves exactly once, even though the SDK callback and the timeout may run on different threads. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Harden the awaitable logout() so `await logout()` can never hang if the SDK completion never fires: add a 10s main-queue timeout fallback and a `settled` guard so the promise resolves exactly once. Companion to the Android change; both platforms now share the same 10s settle behavior. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Carried from #97 (closed). startObserving() replayed the current auth state to JS only when a change was missed while unobserved (pendingObservingState). Because the JS-side state copy starts from a default and is only corrected by events, a (re)subscribe that races a native state change left JS permanently stale — e.g. a logout during app-level teardown left useAuth() stuck authenticated. Replay unconditionally so a listener attach always resyncs JS. The companion subscribe() sink-disposal fix from #97 already landed via #100 (FR-25940); this carries only the remaining startObserving() piece. Co-Authored-By: Adam Rowe <52685+airowe@users.noreply.github.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
dianaKhortiuk-frontegg
force-pushed
the
fix/android-logout-timeout
branch
from
July 24, 2026 09:59
84d3577 to
6828767
Compare
Collaborator
Author
|
Consolidated into #104 — combined with the other two RN release-prep PRs (cherry-picked onto current |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes
logout()awaitable on both platforms and hardens it soawait logout()can never hang.Two layers:
Awaitable logout (both platforms). The bridge now resolves a promise from the native SDK's logout completion instead of being fire-and-forget, and
logout()is typedPromise<void>in JS. This portion originates from external contribution fix: make logout() awaitable on both platforms — resolve when the session actually ends #98 (Adam Rowe / Healthie) and is included here as the base.Always-settle timeout hardening (this PR's addition). As submitted, the promise resolved only from the SDK completion callback — if that callback never fired,
await logout()would hang forever. Both platforms now schedule a 10s fallback and resolve exactly once:ios/FronteggRN.swift):settledguard +DispatchQueue.main.asyncAfter(deadline: .now() + 10).FronteggRNModule.kt):handler.postDelayed(..., 10s)+AtomicBoolean.compareAndSetguard (the SDK callback may land on a background thread while the timeout runs on the main looper, so the guard is atomic).Provenance / review note
The awaitable-logout base comes from a customer fork PR (#98). It was reviewed against the actual diff — no behavioral concerns beyond the hang risk, which this PR closes. Relates to #97 (auth-event delivery parity) and supersedes the Android/iOS halves of #98.
Compatibility
export function logout()already returned the bridge call, so existing callers that ignore the return value are unaffected; callers can nowawaitit. Completion is success-only on both SDKs, so there is no reject path — the promise always resolves.Validation
Files:
android/.../FronteggRNModule.kt,ios/FronteggRN.swift,ios/FronteggRN.m,src/FronteggNative.ts.🤖 Generated with Claude Code