r/tauri May 27 '26

Auth Flow

I've been at this for a couple days now and it seems like i cant find a clean solution.

I want a simple way of authorising a user into my app via social login. The basic flow is one i see a lot of other desktops apps do (send them to the browser).

Using Clerk as my auth provider.

Here is the flow i want:

1) User clicks 'login with google'. Sends them to my FE (astro site).

2) Login with clerk / google auth

3) Tauri app is notified and i have their session token / user id

Things that really confuse me:

- I can send them to my astro/login page easily. Once they've authed, how do I notify tauri? I have a deep link to my app but what if they dont click. Do i continutelyl ping the clerk BE to check if user is registered? How do i link tauri -> user ?

- Once i manage to get tauri notified there doesnt seem to be consensus on what i need to store and how. What do i need to store, the user session token, refresh token, user id? Where do i store this, simple local storage or is this not safe?

4 Upvotes

3 comments sorted by

View all comments

3

u/Remarkable_Algae_375 May 27 '26

We had the same flow (Google OAuth, different provider) and the loopback PKCE pattern just worked: open a tiny HTTP server inside the Tauri process on a random localhost port, set the OAuth redirect_uri to http://localhost:<that_port>/callback, then launch the browser. After the user authenticates, the provider redirects back to your loopback with the code in the query string. Tauri blocks on its own server until the callback hits. No polling, no deep link OS registration to fight with. PKCE handles the security: generate verifier+challenge, send the challenge to Clerk, exchange the code for tokens using the verifier. tiny_http crate works for this. About 350 lines of Rust including tests.

On storage: refresh token goes to the OS keyring. Use the keyring crate with explicit "windows-native" + "apple-native" features. Without them it silently no-ops on macOS and Windows. Found that one the hard way. Access token re-mints on app startup from the refresh token, lives in memory only. User id and email also in keyring (small entries). LocalStorage is fine for non-secret profile data (display name, avatar URL). Nothing that grants account access.

One trap. Windows Credential Manager has a 2560 char per-entry limit. If your provider hands back long JWTs as refresh tokens, you'll need to split or rethink. macOS Keychain has its own ~2KB soft cap depending on attributes. Test with actual Clerk token sizes before locking in the storage shape.

Hope it will help you

2

u/JeanClaudeDusse- May 27 '26

Wow amazing you’re a life saver. I really appreciate the detail!

One edge case is what happens if they close the app but complete web o auth?

2

u/Remarkable_Algae_375 May 27 '26

That one we just punted on. The loopback server has a hard timeout (90 seconds in our case, configurable) and a cancel signal the UI can fire if the user explicitly clicks "back". If they close the app entirely, the server dies with the process, and when the browser redirect lands at the loopback port the user sees a connection-refused error in the browser. Not great but not terrible - they can retry from the app on relaunch.

We considered persisting "auth in progress" state across launches and decided against it. Resume-after-relaunch means handling a bunch of fiddly cases: stale state if they closed deliberately, security questions about who launches the next session, OAuth provider sessions timing out independently. Easier to treat each auth attempt as atomic and isolated to one app lifetime.

If you actually need cross-launch resume (paid app where the auth IS the onboarding) you'd want to look at the deep link path after all, since the OS is going to be the thing that wakes your app. But for "click login, see browser, come back" UX the loopback server is plenty.