Skip to content

Desktop: persist auth token to disk when Credential Manager is restricted#6303

Open
ConnorYoh wants to merge 2 commits intomainfrom
claude/friendly-bhabha-1b0c3f
Open

Desktop: persist auth token to disk when Credential Manager is restricted#6303
ConnorYoh wants to merge 2 commits intomainfrom
claude/friendly-bhabha-1b0c3f

Conversation

@ConnorYoh
Copy link
Copy Markdown
Member

Description of Changes

What was changed

On the desktop (Tauri) app the access token is stored via the keyring Rust crate, which on Windows uses Credential Manager. save_auth_token (in frontend/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_token already had a Tauri-Store-on-disk fallback for this exact scenario — save_auth_token did not, and that asymmetry was the bug.

This PR makes save_auth_token / get_auth_token / clear_auth_token mirror 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 to tokens.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; on NoEntry or error, read from tokens.json.
  • clear_auth_token — clear both stores.

No frontend changes — authService.ts already calls these via invoke() 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:

  • User info (stored as plain JSON in connection.json on disk) persists fine, so the UI shows the user as "logged in".
  • The access token (keyring only) does not persist between launches on their machine, so every API call 401s.
  • Clicking "sign in" completes OAuth successfully, but save_auth_token returns Err("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):

  1. Group Policy Network access: Do not allow storage of passwords and credentials for network authentication — wipes Credential Manager entries on logoff.
  2. Roaming profiles — DPAPI master keys can be re-created on logon, invalidating previously stored credentials.
  3. AV/EDR with credential-protection rules (CrowdStrike/SentinelOne/McAfee, Defender ASR rule "Block credential stealing from LSASS") — block third-party reads/writes to Credential Manager even for signed binaries.

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 environment
  • Auth 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.json when keyring is unavailable is no weaker than what we already do for the refresh token.


Checklist

General

Testing (if applicable)

  • I have run task check to verify linters, typechecks, and tests pass — cargo check only; full task check not run
  • I have tested my changes locally — needs a managed Win10 Pro VM (or Win10 with the GPO above set) to repro the original failure end-to-end. Reviewer guidance below.

Reviewer notes / how to verify

  1. Win11 / unrestricted Win10: log in, close, reopen → still logged in (regression check). Logs should show Auth token saved to keyring. tokens.json should not contain an auth_token entry (keyring is authoritative).
  2. Win10 Pro with Credential Manager restricted (or set the GPO Network access: Do not allow storage of passwords and credentials for network authentication to Enabled): without this fix → forced re-login + re-login fails. With this fix → stays logged in across launches. Logs show Auth token saved to Tauri Store (fallback). tokens.json contains both auth_token and refresh_token.
  3. The customer-facing PR target is the affected Win10 Pro user — once shipped we'll send them a build and confirm before closing the support ticket.

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.
@dosubot dosubot Bot added size:L This PR changes 100-499 lines ignoring generated files. Bugfix Pull requests that fix bugs labels May 1, 2026
@stirlingbot stirlingbot Bot added Front End Issues or pull requests related to front-end development Tauri Pull requests that update Tauri code and removed Bugfix Pull requests that fix bugs labels May 1, 2026
Comment thread frontend/src-tauri/src/commands/auth.rs Outdated
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.
@stirlingbot
Copy link
Copy Markdown
Contributor

stirlingbot Bot commented May 1, 2026

🚀 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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

📦 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
🍎 macOS Intel: Download Stirling-PDF-macos-x86_64 (.dmg) - 212.5 MB
🍎 macOS ARM64: Download Stirling-PDF-macos-aarch64 (.dmg) - 210.8 MB
🪟 Windows x64: Download Stirling-PDF-windows-x86_64 (.exe, .msi) - 211.0 MB


Built from commit 71427e6
Artifacts expire in 7 days

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Front End Issues or pull requests related to front-end development size:L This PR changes 100-499 lines ignoring generated files. Tauri Pull requests that update Tauri code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant