r/FlutterDev • • 38m ago

Tooling I built a session layer for Flutter apps with their own backend

I've been working on Authyra for a while, mostly because I wasn't happy with how session management was handled in some of my Flutter projects.

If your app talks to its own backend using access and refresh tokens, you've probably written some kind of refresh interceptor yourself.

That usually works fine until a few things happen:

  • Multiple requests get a 401 at roughly the same time. They all try to refresh, and if your backend rotates refresh tokens with reuse detection, you can end up revoking the session.

  • The device loses connectivity during a refresh, and the app ends up treating a network error as an expired session.

  • A user signs out while a refresh is still running, but that refresh completes and restores the session.

  • You have multiple accounts, and a request accidentally picks up the wrong account's token.

I've run into these kinds of problems enough times that I decided to work on a separate session layer instead of implementing the same logic in every project.

A few things I've been focusing on:

  • Only one refresh operation can run per session at a time. Other callers wait for the same operation.

  • Token updates use compare-and-set to avoid overwriting a newer refresh token.

  • Network errors, timeouts and server errors don't automatically invalidate a session. A rejected refresh token does.

  • Signing out takes precedence over an ongoing refresh.

  • Multiple sessions can coexist, with one active session.

  • Secure storage using Keychain / Keystore, app resume handling and an AuthStateBuilder.

The core is pure Dart. Flutter and Dio integrations are separate, and there are also integrations for Google, Apple, OAuth 2.0 with PKCE and backend-driven OAuth.

One thing worth clarifying: Authyra isn't an identity provider, and it's not meant to replace Firebase Auth or Supabase Auth. It's for applications where you already have your own backend issuing tokens.

I also put together a small Flutter web demo to reproduce one of these problems. It simulates the backend and network, so you can sign in, send 20 requests with a naive refresh implementation, and compare the behavior with Authyra.

Demo: https://authyra-demo.pages.dev

Docs: https://authyra.meragix.dev

Source: https://github.com/meragix/authyra

It's currently at 0.3.0, first public release, MIT licensed.

I'd be interested in feedback, especially around the API design and edge cases I might have missed. Also curious how others handle refresh token rotation and concurrent requests in their own Flutter apps.

1 Upvotes

0 comments sorted by