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

user() is null on first invocation after Magic Link sign in #143

Closed
joanllenas opened this issue Oct 8, 2021 · 8 comments
Closed

user() is null on first invocation after Magic Link sign in #143

joanllenas opened this issue Oct 8, 2021 · 8 comments
Labels

Comments

@joanllenas
Copy link

Bug report

Describe the bug

When you sign in via Magic Link from an email, the user is null initially.
In order to successfully initialize my app I have to use a setTimeout:

if (supabase.auth.user()) {
  initializeApp(supabase);
} else {
  setTimeout(() => initializeApp(supabase), 1000);
}

To Reproduce

const supabase = createClient(supabaseUrl, supabaseAnonKey);
console.log("supabase.auth.token", localStorage.getItem("supabase.auth.token")); // null
console.log("User", supabase.auth.user()); // null
supabase.auth.onAuthStateChange((evt, session) => {
  console.log("onAuthStateChange.evt", evt); // 'SIGNED_IN'
  console.log("onAuthStateChange.session", session); // { access_token, user, (...) }
});

Expected behavior

I would say that there are at least two possible expected behaviours:

  1. Ideally, make sure that supabase.auth.user() is synchronous for all cases.
  2. If 1. is not possible, add a new 'NOT_SIGNED_IN' event to supabase.auth.onAuthStateChange.

System information

  • OS: macOS
  • Browser chrome 94.0.4606.71
  • Version of supabase-js: 1.24.0
  • Version of Node.js: 14.17.6

Additional context

Related to #23

@joanllenas joanllenas added the bug Something isn't working label Oct 8, 2021
@chipilov
Copy link

chipilov commented Nov 16, 2021

I think the problem goes deeper than this and doesn't only affect magic links.

The issue is that on initial page load, there are 3 possible scenarios:

  1. There is no token stored in local storage - in this case, supabase.auth.user() will return null immediately after calling createClient() and will stay null until the user logs in explicitly;
  2. There is a token stored in local storage and it has NOT expired - in this case, supabase.auth.user() will return non-null immediately after calling createClient() (as long as localStorage API used is synchronous, which is the case for browsers);
  3. a) There is a token stored in local storage, however, it is expired and needs to be refreshed BEFORE the user is considered authenticated - in this case, supabase.auth.user() will return null immediately after calling createClient(), however, as soon as the request for refreshing the token succeeds, onAuthStateChanged handlers will be invoked and supabase.auth.user() will return non-null.
    b) The user has clicked on the confirmation e-mail after registration - in this case, supabase.auth.user() will return null immediately after calling createClient(), however, as soon as the user's access token from the confirmation link is verified (via a REST call), the user will bed signed-in.

Unless I am missing something, there is no way for a developer to differentiate between (1) and (3) if supabase.auth.user() returns null. If it is (3) then you don't want to redirect the user to a login page because you just need to wait a bit until their token is refreshed (i.e. wait until onAuthStateChanged() is fired). If it is (1), however, you do want to redirect them.

It seems to me that the only way to currently know what to do is to manually inspect local storage to see if there is a token inside. However, this does NOT seem like a good option since it relies on the internals of the GoTrue client.

Regarding @joanllenas 's suggestions above:

  1. Making user() by synchronous always doesn't seem possible because of the scenario where a token is present in localStorage but needs to be refreshed. Also, I am not sure if this is possible even for non-expired tokens in environments whereh localStorage is async (e.g. react-native, as far as I know);
  2. This seems like an option but ONLY if it is guaranteed that a subscriber will receive at least one event after subscription. Otherwise, with the current implementation, the event will most likely be dispatched BEFORE the user has had a chance to subscribe for it.

@megacherry
Copy link

Is there something new on this issue? Since using supabase i'm facing this issue that the first request for the session is null.

@linoadmin
Copy link

This is also an issue for me with Facebook. I think if gotrue just opened the OAuth provider in another tab it would work.

The redirects by the providers break the OAuth State Listener.

@kungpaogao
Copy link

Seems like this is the base issue: #460

@github-actions
Copy link
Contributor

github-actions bot commented Jun 7, 2022

🎉 This issue has been resolved in version 1.23.0-next.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@github-actions
Copy link
Contributor

🎉 This issue has been resolved in version 2.0.0-rc.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@hf
Copy link
Contributor

hf commented Dec 30, 2022

This issue has been inactive for a while and I believe the underlying issues have already been addressed with version 2.

@hf hf closed this as completed Dec 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants