fix(auth, android): surface the error code when getIdToken() fails - #18605
fix(auth, android): surface the error code when getIdToken() fails#18605dyt9120 wants to merge 1 commit into
Conversation
`getIdToken()` awaits the native Task with `Tasks.await()` (since firebase#11362), which reports a failed Task as an `ExecutionException` wrapping the Task's own exception. `parserExceptionToFlutter` only read the error code off the exception it was handed, so every refused refresh — a disabled or deleted account, a revoked token — reached Dart as `[firebase_auth/unknown]` with the message "The user's credential is no longer valid. The user must sign in again.", instead of `user-disabled`, `user-not-found` or `user-token-expired`, the codes the other platforms produce (the `[firebase_auth/unknown]` seen in firebase#18561 is this). Unwrap the `ExecutionException` to its cause before classifying, and add an e2e test that disables the signed-in account behind its back and expects `user-disabled` from a forced refresh.
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 the 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 counterproductive. 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. |
|
Hi @dyt9120, thanks for the contribution. This LGTM! Kindly sign CLA and resolve the formatting issues in ci so I can approve. Thanks |
Description
On Android, a token refresh the backend refuses — the account was disabled or deleted, or its refresh token revoked — reaches Dart from
User.getIdToken()/getIdTokenResult()as[firebase_auth/unknown](messageThe user's credential is no longer valid. The user must sign in again.orThe user account has been disabled by an administrator.) instead ofuser-token-expired/user-not-found/user-disabled, the codes iOS and web produce for the same situation. An app that branches on the code to sign a dead session out never sees it on Android.Cause. Since #11362,
getIdTokenawaits the native Task withTasks.await(), which reports a failed Task as ajava.util.concurrent.ExecutionExceptionwrapping the Task's own exception.FlutterFirebaseAuthPluginException.parserExceptionToFlutteronly reads the error code off the exception it is handed (nativeException is FirebaseAuthException), so the wrappedFirebaseAuthInvalidUserExceptionis never looked at andcodestaysUNKNOWN. The three network-ish arms already checkcause, which is whynetwork-request-failedsurvived that change and the auth codes did not.Fix. Unwrap an
ExecutionExceptionto its cause before classifying.getIdTokenis the onlyTasks.awaitcall site in the plugin, so this is the only path affected. The message is unchanged — it already came from the cause throughExecutionException.getMessage()and the Dart side'ssplit(': ').last— only the code changes.Verified on an Android 13 (API 33) emulator against the Auth emulator: disabling the signed-in account behind its back and forcing a refresh yields
user-disabledwith this change andunknownwithout it. The added e2e test (firebase_auth_user_e2e_test.dart,getIdToken()group) does the same through the existingemulatorDisableUserhelper; it passes on iOS and web today and fails on Android without the fix.Related Issues
[firebase_auth/unknown] "The user's credential is no longer valid…"noted in step 3 of [firebase_auth] getIdTokenResult() throws an uncatchable fatal exception on Android when the native token refresh fails on a background thread #18561's repro is this bug.getIdToken()IllegalStateExceptioncrash fix #11362.Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]).This will ensure a smooth and quick review process. Updating the
pubspec.yamland changelogs is not required.///). — none needed; the change is internal to the Android plugin.melos run analyze) does not report any problems on my PR. — not run locally (sparse checkout); the only Dart change is one e2e test written in the surrounding file's style.Breaking Change
Does your PR require plugin users to manually update their apps to accommodate your change?