fix: make QR-code login and endpoint switch reliable (PROD-8200) - #311
Open
deaflynx wants to merge 8 commits into
Open
fix: make QR-code login and endpoint switch reliable (PROD-8200)#311deaflynx wants to merge 8 commits into
deaflynx wants to merge 8 commits into
Conversation
…t-client Feat/migrate new dart client
…-back-button fix(dashboard): make system back mirror the AppBar back arrow
…gsboard#303) - Read the live ThingsboardClient via getter in Login and NotificationService: after a QR endpoint switch re-creates the client, captured references kept hitting the old host with new tokens (401 'Token is outdated'), and the failed refresh wiped the fresh session. - Rework NoauthProvider.switchEndpoint: stage the exchanged JWT pair in storage before reInit so the new client can only start with exactly these tokens (a stale session left in storage can no longer win the race), roll back to the previous endpoint (not the compiled default) on failure, and surface the server's error message instead of raw Dio text. - Handle QR links without a secret (the login-page app QR): switch the host and land on the new host's login page instead of spinning forever; SwitchEndpointArgs.secret is now optional. - Never render ThingsboardError.toString() in the noauth view (it embeds the stacktrace); navigate on isDone and add a fallback so the user is never stranded on the spinner. - Restore app-link handling in the v2 router (the TbContext listener is no longer initialized): listen in the app root, consume the cold-start link, and drop platform duplicate deliveries. - Pop the QR scanner once per scan: repeated MLKit detections popped the route twice ('There is nothing to pop'). - Guard fire-and-forget handleUserLoaded calls against unhandled async errors.
…8200) The dart client is autogenerated and must stay unmodified, so: - TbClientService suppresses error toasts while client.init() runs (init and reInit): the client's internal best-effort version check hits /api/admin/updates, which answers 403 for non-SYS_ADMIN users and otherwise surfaced as an error toast on every (re)init. Real init failures still propagate and are handled by the callers. - switchEndpoint re-applies the exchanged JWT pair to the new client if it comes out of reInit unauthenticated: a failing background refresh of the previous session may clear the shared token storage after the pair was staged but before init read it.
getLoginMobileInfo already has a graceful fallback (QR-only button list), but its failure still surfaced through the interceptor's global error channel as a 'You don't have permission' toast right after a successful QR switch: some servers answer 403 for an unknown mobile package. Pass ignoreErrors/ignoreLoading via the request extras so the interceptor stays quiet; the fallback behavior is unchanged.
…-8200) Two more sources of the 'You don't have permission' toast right after a successful QR switch: - NotificationService mobile-session calls (get/save/removeMobileSession, unread count) run against servers that may not know the mobile package and answer 403. Mark them ignoreErrors/ignoreLoading and guard the session sync so notification setup failures never surface to the user or abort init. - The generated client delivers error callbacks via Future(() => cb()), so the internal version-check 403 raised during client.init() reaches onClientError one event-loop turn AFTER init() returns - just outside the suppression window. Release the suppression flag after a short grace period instead of synchronously.
The JWT pair returned for a QR secret is bound to the secret, so re-scanning the same code after a logout hands the app tokens issued before the logout watermark: the exchange succeeds but every authenticated call answers 401 'Token is outdated', which sent the switch into a silent ~10s login/refresh loop that ended on the login page with no explanation. Verify the pair with GET /api/auth/user on the target host before committing the switch: a rejected pair now shows the server's message within seconds and rolls back, same as an expired QR code.
… into fix/prod-8200-qr-host-switch # Conflicts: # lib/core/auth/noauth/provider/noauth_provider.g.dart
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.
Merge of the CE fix branch into PE. Fixes PROD-8200; fixes #303. CE counterpart: thingsboard/flutter_thingsboard_app#247.
Summary
QR-code login and host switching were unreliable: stale-client 401 storms wiped the fresh session after a switch ('Token is outdated', fixed only by force-restarting the app), raw stacktraces and irrelevant 'You don't have permission' toasts surfaced on screen, QR links without a secret span forever, camera-scanned app links were silently dropped, and re-scanning a QR after logout put the app into a silent login/refresh loop.
See thingsboard/flutter_thingsboard_app#247 for the full root-cause analysis and change list.
PE-specific notes
ce-origin/fix/prod-8200-qr-host-switch(single conflict in generatednoauth_provider.g.dart, regenerated with build_runner).thingsboard_app_pe.dart(the PE root widget), sincethingsboard_app.dartexports the PE variant.login_provider.dart(custom translations, user permissions) is preserved on top of the fix.Testing
The underlying fixes were verified end-to-end on the CE app (emulator + on-device scanner runs against a local TB instance and demo.thingsboard.io): QR switch with auto-login, same-host relogin, re-scan within TTL, re-scan after logout (clean server message + rollback), expired secret, no-secret host switch, logout/login regression — zero unhandled exceptions. PE merge:
flutter analyzeat the develop/1.9.0 baseline (no new findings).