fix(auth, windows): add opt-in flag to skip id-token EventChannel (FAST_FAIL_INVALID_ARG workaround)#18223
Conversation
Adds FirebaseAuthPlatform.disableIdTokenChannelOnWindows, an opt-in static flag that — when set to rue before Firebase.initializeApp() — skips the id-token EventChannel subscription in MethodChannelFirebaseAuth's constructor on Windows. Default behavior is unchanged. Linux, macOS, Android, iOS, and Web are not touched. This is a stopgap workaround for the upstream Windows native threading bug tracked in firebase#18210 and flutter/flutter#134346: the native Windows firebase_auth plugin dispatches id-token events from a background thread, causing the Flutter engine to abort the process with FAST_FAIL_INVALID_ARG (0xc0000409 / STATUS_STACK_BUFFER_OVERRUN) shortly after sign-in. Every Dart-side mitigation suggested in the linked threads runs after the native side has already dispatched from the wrong thread and cannot prevent the abort. Affected apps currently have no supported workaround. Trade-off when enabled on Windows: - authStateChanges() — unaffected. - idTokenChanges() / userChanges() — still fire on sign-in / sign-out (via the separate auth-state channel). Mid-session token-refresh events (e.g. custom-claims updates) are not observed until the underlying engine fix ships. - getIdToken() / getIdTokenResult() — unaffected. The flag is a temporary mitigation and can be deleted once the engine fix lands and firebase_auth_desktop adopts a platform-thread dispatch primitive (see flutter/flutter#134346 comment thread). Related: firebase#18210, firebase#13340, firebase#16888, firebase#17800, firebase#11933 Made-with: Cursor
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. |
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Summary
Adds
FirebaseAuthPlatform.disableIdTokenChannelOnWindows, an opt-instatic flag that — when set to
truebeforeFirebase.initializeApp()— skips theid-tokenEventChannelsubscription in
MethodChannelFirebaseAuth's constructor on Windows.Default behavior is unchanged. Linux, macOS, Android, iOS, and Web are
not touched. The flag is a plain static
boolso it is reachablefrom user code before
MethodChannelFirebaseAuth's constructorruns (any instance-level setter would arrive too late — the listener
is registered the moment
FirebaseAuthPlatform.instanceis firstaccessed).
Fixes #18210. Related: #13340, #16888, #17800, #11933.
Why
The Windows
firebase_auth_plugindispatchesid-tokeneventsfrom a native background thread. Flutter's engine requires platform
channel traffic on the platform thread and raises a
FAST_FAIL_INVALID_ARG(0xc0000409/STATUS_STACK_BUFFER_OVERRUN) abort when that contract is violated.Users hit this as a silent process termination shortly after
signInWithEmailAndPassword()or on cold starts with a cachedrefresh token. cdb confirms the crashing frame:
The true fix is upstream in the Flutter engine
(flutter/flutter#134346 — open since Sep 2023, currently P2). Until
FlutterDesktopEnginePostPlatformThreadTask(or equivalent) shipsand
firebase_auth_desktopadopts it, affected apps have nosupported workaround: every Dart-side mitigation suggested in the
linked threads (
Future.microtask,WidgetsBinding.addPostFrameCallback,Future.delayed,runZonedGuarded, customBinaryMessenger) runs after the nativeside has already dispatched from the wrong thread and cannot prevent
the abort. Not subscribing to
idTokenChanges()in user codedoesn't help either — the listener is attached unconditionally by the
platform-interface constructor.
This PR gives affected apps an explicit, opt-in escape hatch that:
and its one call site).
What changes
FirebaseAuthPlatform.disableIdTokenChannelOnWindows— a newstatic
boolfield, defaultfalse, documented with links tothe upstream tickets.
MethodChannelFirebaseAuth's constructor — guards the id-tokenEventChannelregistration with_shouldSkipIdTokenChannel()which only returns
truewhen the flag is set and the hostis Windows (and not web).
disable_id_token_channel_on_windows_test.dartcovering the flag's default and toggle behavior.
No Pigeon, platform-interface-breaking, or generated-code changes.
No CHANGELOG edit — Melos generates that on release from the
conventional commit message.
Scope / trade-offs when the flag is enabled on Windows
Fully unaffected — every imperative API and the most common
observer:
signInWithEmailAndPassword,signInWithCredential,signInWithCustomToken,signInAnonymously, phone, popup, redirect).signOut(),createUserWithEmailAndPassword().authStateChanges()stream — full fidelity (separate channel,already dispatched from the platform thread). Fires on sign-in,
sign-out, and cold-start-with-cached-user.
FirebaseAuth.instance.currentUser— populated correctly by_handleAuthStateChangesListenerand by synchronous assignmentinside every sign-in method.
user.getIdToken()/user.getIdToken(true)/user.getIdTokenResult(forceRefresh: true)— imperative RPCs,unaffected.
updateDisplayName,updateEmail,updatePassword,updatePhoneNumber,updateProfile,reload,unlink,delete,reauthenticateWithCredential,verifyBeforeUpdateEmail, etc.sendPasswordResetEmail,confirmPasswordReset,applyActionCode,checkActionCode,verifyPasswordResetCode.useAuthEmulator, tenant ID, customauth domain.
Degraded — the real trade-off:
idTokenChanges()stream goes silent on Windows. Never emits —not on sign-in, sign-out, token refresh, nor custom-claims updates.
userChanges()stream loses native-driven emissions. It stillemits when the app itself calls profile-mutation methods
(
updateProfile,updateEmail,reload, etc.) becausethose invoke
sendAuthChangesEventdirectly. It stops emittingfrom native sources (sign-in/out, token refresh, admin-driven
custom-claims changes).
client via streams. Workaround: imperatively call
user.getIdToken(true)when you need fresh claims.This is strictly better than the current Windows status quo (process
abort on every cached login) for every app that does not rely on live
custom-claims stream notifications — which is most apps.
Test plan
flutter testforfirebase_auth_platform_interface— all 181tests pass, including the 2 new ones in
disable_id_token_channel_on_windows_test.dart.dart analyze lib test— no issues.dart format --set-exit-if-changed— no diff.firebase_auth 6.4.0 / firebase_auth_platform_interface 8.1.9 via a
local
dependency_override:0xc0000409abort on cached-login coldstart, reproduced.
Firebase.initializeApp(): no crash;authStateChanges()fires correctly on sign-in, sign-out, andcold-start-with-cached-user; app stable for 40s+ of sync traffic.
Usage
Follow-up (out of scope for this PR)
lands and
firebase_auth_desktopdispatches its native eventcallbacks onto the platform thread.