Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update README and docs to explain JWT refresh flow #805

Closed
elliottetzkorn opened this issue Jan 22, 2024 · 12 comments · Fixed by #807
Closed

Update README and docs to explain JWT refresh flow #805

elliottetzkorn opened this issue Jan 22, 2024 · 12 comments · Fixed by #807
Labels
auth This issue or pull request is related to authentication enhancement New feature or request

Comments

@elliottetzkorn
Copy link
Contributor

elliottetzkorn commented Jan 22, 2024

Right now it is very confusing how to handle the JWT refresh flow for supabase with flutter. It is my understanding that the supabase package is supposed to generate a new access token automatically, but this is not a clear flow.

For example: are currentUser and currentSession reliably not-null anytime a user is authenticated? I have run into situations where they appear temporarily null inspite of the user being logged in. This has broken key parts of my app UI.

Is there any code needed on the client side to handle JWT refresh?

Are we supposed to listen to onAuthStateChanged to handle the JWT refresh?

Really a simple guide for Supabase and Flutter using something like Provider around persisting auth state and handling the JWT refresh would be immensely appreciated. As it stands this flow is very hard to figure out.

@elliottetzkorn elliottetzkorn added the enhancement New feature or request label Jan 22, 2024
@elliottetzkorn
Copy link
Contributor Author

elliottetzkorn commented Jan 22, 2024

For example I see this code

supabase.auth.onAuthStateChanged
.listen((data) {})
.onError((error) {
  supabase.auth.refreshSession();  
});

from another issue: #452 (comment)

Is this the recommended way to handle refresh?

@elliottetzkorn
Copy link
Contributor Author

elliottetzkorn commented Jan 22, 2024

Right now I have added some code like this:

  static Future<void> safeNetworkCall(BuildContext context, AsyncCallback call,
      Function postAction, VoidCallback? errorAction, bool silent) async {
    try {
      if ((Supabase.instance.client.auth.currentSession == null &&
              context.read<ProfileNotifier>().id != null) ||
          (Supabase.instance.client.auth.currentSession != null &&
              Supabase.instance.client.auth.currentSession!.isExpired)) {
        await Supabase.instance.client.auth.refreshSession();
      }

      await call().then((value) {
        postAction(value);
      });
    } on PostgrestException catch (e) {
      if (errorAction != null) {
        if (!silent) showError(context, e.message);
        errorAction();
      }
    } catch (e) {
      if (errorAction != null) {
        if (!silent) showError(context, e.toString());
        errorAction();
      }
    }
  }

Where ProfileNotifier is the Provider class which holds onto the user reference.. so I am forcing a refresh token call before every network call if either the session has disappeared but the user is logged in (the provider class holds a valid id), or if the session is present but the token has expired.

Does this make sense? Am I handling this correctly?

@elliottetzkorn
Copy link
Contributor Author

I am also not relying on the session state for any of my UI since I have found it to be unreliable. I am relying only on my user state Provider for that. Should we be able to depend on session state for UI? If it is true that we cannot this is something else which I think should be really explicitly documented.

@dshukertjr dshukertjr added the auth This issue or pull request is related to authentication label Jan 22, 2024
@dshukertjr
Copy link
Member

@ellmaki
supabase_flutter will automatically refresh your access token, and there is nothing you need to do. The SDK will automatically update the token if the session has expired when making requests. You shouldn't ever have to call refreshSession() either.

Would you explain why you thought you had to implement the complicated workarounds you have shared?

@dshukertjr
Copy link
Member

I am also not relying on the session state for any of my UI since I have found it to be unreliable. I am relying only on my user state Provider for that. Should we be able to depend on session state for UI? If it is true that we cannot this is something else which I think should be really explicitly documented.

Yes, you can rely on the Supabase auth state in your UI. If supabase.auth.currentSession is not null, the user is signed in.

@elliottetzkorn
Copy link
Contributor Author

I think this was possibly the source of all of my problems #806

@dshukertjr
Copy link
Member

That sounds good, and sorry for the confusion.

@elliottetzkorn
Copy link
Contributor Author

Thanks for addressing it quickly.

@elliottetzkorn
Copy link
Contributor Author

@dshukertjr I want to verify that things are fixed on my end - do you have advice for simulating a JWT expiration event?

@dshukertjr
Copy link
Member

@ellmaki
Yeah, it's not really a simulation, but the easiest way to test it would be to set the JWT expiry limit to something very short. I have it set to 60 seconds here. Then your access token will expire every 60 seconds.

Screenshot 2024-01-24 at 14 55 53

@elliottetzkorn
Copy link
Contributor Author

Thank you. Through forcing the expiration I have confirmed that my bugs came from the currentUser null issue.

@dshukertjr
Copy link
Member

Glad to hear that things are working out for you now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auth This issue or pull request is related to authentication enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants