Persist Snapmaker cloud login across restarts (secure token store + startup race fix) - #479
Persist Snapmaker cloud login across restarts (secure token store + startup race fix)#479PGMacDesign wants to merge 2 commits into
Conversation
Snapmaker cloud login was not persisted on Linux/AppImage (and elsewhere): every restart forced a fresh OAuth login. Persist the session so it survives restarts, revalidating the stored token on startup. - Store only the bearer token, and only in the OS secret store via wxSecretStore (libsecret / Credential Manager / Keychain) -- never in plaintext config. If no secret service is available the token is not persisted (falls back to the prior re-login behaviour) rather than written insecurely. Guarded with wxUSE_SECRETSTORE so toolchains without it (e.g. MinGW) still compile. - On startup, revalidate the token against the accounts/current endpoint and re-fetch the profile from the server, restoring the session; clear the stored token on failure or explicit logout. No user data is written to disk. Addresses Snapmaker#116, Snapmaker#226. Builds on the approach proposed in Snapmaker#266, hardened to keep the token out of plaintext on disk.
The persisted session is revalidated asynchronously at startup. That can complete before the Flutter home page subscribes to login-state updates, in which case the one-shot user_login_notify() push reaches an empty subscriber list and is lost -- leaving the UI showing 'logged out' despite a valid, restored token. Make sw_SubscribeUserLoginState push the current login state immediately when the user is already logged in at subscribe time. This closes the race in both orderings: restore-before-subscribe is covered by the immediate push here, and restore-after-subscribe by the existing notify() path.
|
@coderabbitai review |
|
And still not added to the latest release -.- |
|
Independent confirmation of the second half of your root cause, from a third install type, plus one adjacent case this PR may not cover. Environment
With #116 at 2.2.1 and #226 at 2.4.3, the symptom spans at least 2.2.1 → 2.4.3 across AppImage and Flatpak. The token is on disk and valid at launch — something deletes it The session token does get written to the embedded webview's localStorage and it survives a clean quit. Read back before launching: So there is a valid token present at the next start, and login is still demanded. That matches your "even once restored, the UI shows logged-out despite a valid token" description. The log sequence, before any UI appears
Worth checking against your race fix: if the empty-state push can still reach Possibly out of scope for this PR: the localhost port rotates, splitting localStorage The local server port is not fixed. When 13619 is occupied (second instance, or a stale process), startup logs: Webview localStorage is keyed by origin, so that session gets an entirely different store. Both exist here, each with its own If the OS secret store is now the source of truth this may be moot, but any session state still living in a port-keyed origin will be invisible to a session that lands on a fallback port. Either pin the port or keep session state out of the origin. Reproducing the inspection Those stores are plain SQLite: import sqlite3
c = sqlite3.connect('file:http_127.0.0.1_13619.localstorage?mode=ro', uri=True)
for k, v in c.execute("select key, length(value) from ItemTable"):
print(k, v)Keys of interest: Happy to test a build of this branch on Flatpak/2.3.5 if that helps get it reviewed. |

Description
Snapmaker cloud login was not persisted across restarts on Linux (AppImage/Flatpak) and elsewhere — every launch forced a fresh OAuth login. This PR persists the session securely and restores it on startup, with a fix for a startup race that could otherwise leave the UI showing "logged out" despite a valid restored token.
Fixes #116
Fixes #226
Builds on the approach proposed in #266, hardened to keep the token out of plaintext on disk.
1. Persist login across restarts via the OS secret store (
GUI_App.cpp/.hpp,WebSMUserLoginDialog.cpp)wxSecretStore(libsecret / Windows Credential Manager / macOS Keychain) — never in plaintext config.wxUSE_SECRETSTOREso toolchains without it (e.g. MinGW) still compile.accounts/currentendpoint and re-fetch the profile from the server, restoring the session. The stored token is cleared on validation failure or explicit logout. No user data is written to disk.2. Push restored login to the web UI on subscribe (
SSWCP.cpp)user_login_notify()push reaches an empty subscriber list and is lost — leaving the UI "logged out" despite a valid token.sw_SubscribeUserLoginStatenow pushes the current login state immediately when the user is already logged in at subscribe time. This closes the race in both orderings (restore-before-subscribe via the immediate push here; restore-after-subscribe via the existing notify path).Security notes
OrcaSlicer.confor any plaintext file.Breaking changes / dependencies: none. Uses
wxSecretStore(already part of wxWidgets), guarded bywxUSE_SECRETSTORE.Screenshots/Recordings/Graphs
🎉 Can confirm Login works + Persists across app close / open 🎉
Linux (Pop! OS / Ubuntu)
Mac
Tests
wxUSE_SECRETSTORE.