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

Expo - React Native - Auth session missing! #25827

Closed
2 tasks done
thiagoadsix opened this issue May 7, 2024 · 2 comments
Closed
2 tasks done

Expo - React Native - Auth session missing! #25827

thiagoadsix opened this issue May 7, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@thiagoadsix
Copy link

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

I'm trying to reset a password for a user, but every time I attempt to update the password, Supabase returns an error message saying 'Auth session missing!', even though I have already set a new session

To Reproduce

  • I requested to reset my password.
  • I received the email in my inbox.
  • I clicked on the link.
  • I was redirected to the app.
  • I set the new password.
  • I received the error message.

Expected behavior

Once the user is inside the app, he should be able to reset the password.

Screenshots

Here is the print showing the email:
Simulator Screenshot - iPhone 15 - 2024-05-07 at 01 29 36

Here is the moment after I clicked on the link:
Simulator Screenshot - iPhone 15 - 2024-05-07 at 01 29 42

Here is the moment after I clicked on open:
Simulator Screenshot - iPhone 15 - 2024-05-07 at 01 29 48

More informations

Here is my Supabase Context:

import { GoogleSignin } from "@react-native-google-signin/google-signin";
import { Session, User } from "@supabase/supabase-js";
import * as Linking from "expo-linking";
import { usePathname, useRouter, useSegments } from "expo-router";
import React, { createContext, useEffect, useState } from "react";
import { Alert } from "react-native";

import { supabase } from "@/config/supabase";

type SignUpParams = {
  email: string;
  password: string;
  name: string;
  redirectTo: string;
};

type ResetPasswordParams = {
  email: string;
  redirectTo: string;
};

type SupabaseContextProps = {
  user: User | null;
  session: Session | null;
  initialized?: boolean;
  updatePassword: (password: string) => Promise<void>;
  requestResetPassword: ({
    email,
    redirectTo,
  }: ResetPasswordParams) => Promise<void>;
};

type SupabaseProviderProps = {
  children: React.ReactNode;
};

GoogleSignin.configure({
  scopes: ["https://www.googleapis.com/auth/drive.readonly"],
  webClientId: "...",
  iosClientId: "...",
});

const parseSupabaseUrl = (url: string) => {
  let parsedUrl = url;
  if (url.includes("#")) {
    parsedUrl = url.replace("#", "?");
  }

  return parsedUrl;
};

export const SupabaseContext = createContext<SupabaseContextProps>({
  user: null,
  session: null,
  initialized: false,
  updatePassword: async () => {},
  requestResetPassword: async () => {},
});

export const SupabaseProvider = ({ children }: SupabaseProviderProps) => {
  const [user, setUser] = useState<User | null>(null);
  const [session, setSession] = useState<Session | null>(null);
  const [initialized, setInitialized] = useState<boolean>(false);
  const pathname = usePathname();

  const segments = useSegments()[0];
  const router = useRouter();

  const updatePassword = async (password: string) => {
    console.log({ password });
    const { data, error } = await supabase.auth.updateUser({
      password,
    });

    if (error) {
      console.error(error);
      throw error;
    }

    console.log({ data });
  };

  const requestResetPassword = async ({
    email,
    redirectTo,
  }: ResetPasswordParams) => {
    const { error } = await supabase.auth.resetPasswordForEmail(email, {
      redirectTo,
    });

    if (error) {
      throw error;
    }
  };

  useEffect(() => {
    supabase
      .channel("schema-db-changes")
      .on(
        "postgres_changes",
        {
          event: "UPDATE",
          schema: "public",
          table: "roles",
        },
        (payload) => supabase.auth.refreshSession()
      )
      .subscribe();

    supabase
      .channel("schema-db-changes")
      .on(
        "postgres_changes",
        {
          event: "INSERT",
          schema: "public",
          table: "roles",
        },
        (payload) => supabase.auth.refreshSession()
      )
      .subscribe();
  }, []);

  useEffect(() => {
    const { data } = supabase.auth.onAuthStateChange(async (event, session) => {
      setSession(session);
      setUser(session ? session.user : null);
      setInitialized(true);
    });

    return () => {
      data.subscription.unsubscribe();
    };
  }, []);

  useEffect(() => {
    (async () => {
      const url = await Linking.getInitialURL();
      if (url?.includes("reset-password")) {
        const transformedUrl = parseSupabaseUrl(url);
        const parsedUrl = Linking.parse(transformedUrl);

        const accessToken = parsedUrl.queryParams?.access_token;
        const refreshToken = parsedUrl.queryParams?.refresh_token;

        if (
          typeof accessToken === "string" &&
          typeof refreshToken === "string"
        ) {
          try {
            const { data, error } = await supabase.auth.setSession({
              access_token: accessToken,
              refresh_token: refreshToken,
            });

            await supabase.auth.refreshSession();

            if (error) throw error;

            setSession(data.session);
            setUser(session ? session.user : null);

            if (data.session) {
              router.replace("/(app)/settings/reset-password/");
            }
          } catch (error) {
            console.error("Failed to set session:", error);
          }
        }
      }
    })();
  }, []);

  useEffect(() => {
    if (!initialized) return;

    if (!session && pathname !== "/(auth)/welcome") {
      router.replace("/(auth)/welcome");
    } else if (session && !pathname.includes("/settings/reset-password")) {
      router.replace("/(app)/home/");
    }
  }, [initialized, session, segments, router]);

  return (
    <SupabaseContext.Provider
      value={{
        user,
        session,
        initialized,
        updatePassword,
        requestResetPassword,
      }}
    >
      {children}
    </SupabaseContext.Provider>
  );
};

System information

  • OS: [e.g. macOS]
  • Version of @supabase/supabase-js: [e.g. 2.38.0]
  • Version of Node.js: [e.g. 20.10.0]
@thiagoadsix thiagoadsix added the bug Something isn't working label May 7, 2024
@thiagoadsix
Copy link
Author

Maybe I'm missing something about states, react component mounting, or something else that I don't have any idea.

@thiagoadsix
Copy link
Author

I'm trying to update the session from user on this useEffect, but for some reason, this is not updating the session, because Supabase keeps saying: Auth session missing!:

  useEffect(() => {
    (async () => {
      const url = await Linking.getInitialURL();
      if (url?.includes("reset-password")) {
        const transformedUrl = parseSupabaseUrl(url);
        const parsedUrl = Linking.parse(transformedUrl);

        const accessToken = parsedUrl.queryParams?.access_token;
        const refreshToken = parsedUrl.queryParams?.refresh_token;

        if (
          typeof accessToken === "string" &&
          typeof refreshToken === "string"
        ) {
          try {
            const { data, error } = await supabase.auth.setSession({
              access_token: accessToken,
              refresh_token: refreshToken,
            });

            await supabase.auth.refreshSession();

            if (error) throw error;

            setSession(data.session);
            setUser(session ? session.user : null);

            if (data.session) {
              router.replace("/(app)/settings/reset-password/");
            }
          } catch (error) {
            console.error("Failed to set session:", error);
          }
        }
      }
    })();
  }, []);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant