Desktop: persist auth token to disk when Credential Manager is restricted#6303
Open
Desktop: persist auth token to disk when Credential Manager is restricted#6303
Conversation
On managed Windows 10 Pro environments (Group Policy restricting Credential Manager, AV/EDR credential-protection rules, roaming-profile DPAPI quirks), the keyring write succeeds but the read-back returns the wrong value or NoEntry. save_auth_token then errored out, leaving users stuck: user_info still persisted to disk so the UI showed them as "logged in", but every API call 401'd and re-login itself failed because the keyring verification step rejected each fresh OAuth token. Mirror the same keyring-then-Tauri-Store fallback that save_refresh_token already uses: try keyring with read-back verification, fall back to tokens.json on any failure. When keyring works it stays authoritative and any stale fallback copy is cleared, so unaffected users see no behaviour change.
Aikido bot review caught that `let entry = get_keyring_entry()?;` early- returned on entry creation failure, defeating the disk fallback for the worst-case scenario (no keyring service available at all - e.g. headless Linux without secret-service, or fully locked-down Windows). Restructure all three auth-token commands so any keyring failure - including Entry construction - falls through to the Tauri Store path instead of erroring.
Contributor
🚀 V2 Auto-Deployment Complete!Your V2 PR with embedded architecture has been deployed! 🔗 Direct Test URL (non-SSL) http://54.175.155.236:6303 🔐 Secure HTTPS URL: https://6303.ssl.stirlingpdf.cloud This deployment will be automatically cleaned up when the PR is closed. 🔄 Auto-deployed for approved V2 contributors. |
Contributor
📦 Tauri Desktop Builds Ready!The desktop applications have been built and are ready for testing. Download Artifacts:🐧 Linux x64: Download Stirling-PDF-linux-x86_64 (.deb, .rpm, .AppImage) - 729.6 MB Built from commit 71427e6 |
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.
Description of Changes
What was changed
On the desktop (Tauri) app the access token is stored via the
keyringRust crate, which on Windows uses Credential Manager.save_auth_token(infrontend/src-tauri/src/commands/auth.rs) wrote to keyring, then read it back to verify, and returned an error if the read-back didn't match. There was no fallback.save_refresh_tokenalready had a Tauri-Store-on-disk fallback for this exact scenario —save_auth_tokendid not, and that asymmetry was the bug.This PR makes
save_auth_token/get_auth_token/clear_auth_tokenmirror the existing refresh-token fallback pattern:save_auth_token— try keyring with read-back verification; on any failure (set error, read-back mismatch,NoEntry) fall back totokens.json(Tauri Store) instead of returning an error. When keyring works it stays authoritative and any stale fallback copy is cleared.get_auth_token— keyring first; onNoEntryor error, read fromtokens.json.clear_auth_token— clear both stores.No frontend changes —
authService.tsalready calls these viainvoke()and doesn't care which backend stored the value.Why the change was made
A SaaS customer on Windows 10 Pro is forced to re-login every app launch, and the re-login itself fails. The exact symptoms:
connection.jsonon disk) persists fine, so the UI shows the user as "logged in".save_auth_tokenreturnsErr("Token verification failed after save")because the keyring read-back returns the wrong value — so re-login appears to fail.This is consistent with managed Win10 Pro environments where one of the following is in play (these don't typically apply to Win11 Home/Pro used personally):
Network access: Do not allow storage of passwords and credentials for network authentication— wipes Credential Manager entries on logoff.The MSI is signed in CI, so signing is not the cause. The fix is defence-in-depth: even if IT keeps Credential Manager locked down, users stay logged in across launches via the on-disk fallback.
Logs to expect after this change
After login, exactly one of:
Auth token saved to keyring— normal/unrestricted environmentAuth token saved to Tauri Store (fallback)— restricted Credential Manager (Win10 Pro corp, etc.)This is the diagnostic signal we'll want from the affected customer to confirm the fix solved their case.
Security note
The refresh token (the more sensitive long-term credential) already had this exact disk fallback. The access token is a short-lived JWT, so storing it in
tokens.jsonwhen keyring is unavailable is no weaker than what we already do for the refresh token.Checklist
General
cargo checkclean)Testing (if applicable)
task checkto verify linters, typechecks, and tests pass —cargo checkonly; full task check not runReviewer notes / how to verify
Auth token saved to keyring.tokens.jsonshould not contain anauth_tokenentry (keyring is authoritative).Network access: Do not allow storage of passwords and credentials for network authenticationto Enabled): without this fix → forced re-login + re-login fails. With this fix → stays logged in across launches. Logs showAuth token saved to Tauri Store (fallback).tokens.jsoncontains bothauth_tokenandrefresh_token.