rphlmr / supa-fly-stack

The Remix Stack for deploying to Fly with Supabase, authentication, testing, linting, formatting, etc.
MIT License
289 stars 26 forks source link

Handle password recovery for email/password #62

Closed rphlmr closed 1 year ago

rphlmr commented 1 year ago

Will address this asap.

Ashxvi commented 1 year ago

I've tried the same oauth callback for password recovery with the following useEffect :

useEffect(() => {
    if (env.SUPABASE_URL && env.SUPABASE_ANON_PUBLIC) {

      const {
        data: { subscription },
      } = supabase.auth.onAuthStateChange((event, supabaseSession) => {
        if (event === "SIGNED_IN" || event === "PASSWORD_RECOVERY") {

          const refreshToken = supabaseSession?.refresh_token;

          if (!refreshToken) return;

          const formData = new FormData();

          formData.append("refreshToken", refreshToken);

          fetcher.submit(formData, { method: "post", replace: true });
        }
      });

      return () => {
        // prevent memory leak. Listener stays alive 👨‍🎤
        subscription.unsubscribe();
      };
    }
  }, [env.SUPABASE_ANON_PUBLIC, env.SUPABASE_URL, fetcher, supabase.auth]);

The action looks like:

export async function action({ request }: ActionArgs) {
  assertIsPost(request);

  const formData = await request.formData();

  const refreshToken = formData.get("refreshToken") as string;

  if (!refreshToken) {
    return redirect("/login");
  }

  // refresh session
  const authSession = await refreshAccessToken(refreshToken);

  if (!authSession?.email) {
    return json(
      {
        message: "Invalid Refresh Token.",
      },
      { status: 401 }
    );
  }

  const supabase = await getSupabaseServer(authSession?.accessToken);

  const { data, error } = await supabase.auth.updateUser({
    password: "nouveauMotDePasse",
  });

  logger().debug(error);

  // user password updated, commit session
  if (data?.user) {
    const redirectTo = safeRedirect("/dashboard");

    return redirect(redirectTo, {
      headers: {
        "Set-Cookie": await commitAuthSession(request, {
          authSession,
        }),
      },
    });
  }

  logger().warn("oAuth callback - User not found.");

  return json(
    {
      message: "oAuth callback - Error while processing password recovery.",
    },
    { status: 500 }
  );
}

I receive the email then when I click on the link, I'm getting a strange error:

{"name":"AuthSessionMissingError","message":"Auth session missing!","status":400}
DonKoko commented 1 year ago

hey @rphlmr, do you have any update on this? I would love to help somehow if I can.

rphlmr commented 1 year ago

Damn, I need to add "read my todo" in my todo 😅 Wednesday is my "open source day", I will try to address that this Wednesday 🫡

rphlmr commented 1 year ago

Hello, I've just merged a possible implementation ;)

There is a SSR mismatch warning due to the nature of oauth process (callback URL with fragment #, oauth spec).

I think I'll come back to this feature with something different (based on session cookies), but It works as expected for now.

This warning in the console is "expected" because we use a client-side code (supabase authListener) that changes the rendered URL 😅.