supabase-js icon indicating copy to clipboard operation
supabase-js copied to clipboard

React Native - Expo, Password Reset, redirect URL and Exchange authorization code.

Open AHMED-5G opened this issue 1 year ago • 4 comments

Bug report

  • [x] I confirm this is a bug with Supabase, not with my own application.
  • [x] I confirm I have searched the Docs, GitHub Discussions, and Discord.
  • Related issues (#5663), (https://github.com/supabase/auth-helpers/issues/567)

Describe the bug

I am encountering difficulties with the password reset feature in while developing a React Native Expo application. The password reset is not functioning as expected, and I am experiencing inconsistent behavior with the redirect URL. Additionally, how to handle reset password after redirect what is code ? Screenshot from 2023-08-23 02-16-41

Actual Behavior

  • Sometimes it's redirect to base URL exp://127.0.0.1:8081 and some time it is redirecting to provided URL exp://127.0.0.1:8081/--/resetPassword,

  • Then at final approach as supabase docs:


// The code is retrieved from the query parameter - use whichever mechanism is recommended
// for your app/framework. This is just an example.
const code = url.searchParams.get('code')

// call the Supabase API to exchange the code for a session
await supabase.auth.exchangeCodeForSession(code)

However, the query parameter looks like this: exp://127.0.0.1:8081/--/resetPassword#access_token=123&expires_in=3600&refresh_token=123&token_type=bearer&type=recovery"

  • Redirect URLs Screenshot from 2023-08-23 01-20-06

  • Code snippets: supabase.ts

import "react-native-url-polyfill/auto";
import * as SecureStore from "expo-secure-store";
import { createClient } from "@supabase/supabase-js";
import { SUPABASE_ANON_KEY } from "@env";
import { SupabaseAuthClientOptions } from "@supabase/supabase-js/dist/module/lib/types";

const ExpoSecureStoreAdapter = {
  getItem: (key: string) => {
    return SecureStore.getItemAsync(key);
  },
  setItem: (key: string, value: string) => {
    SecureStore.setItemAsync(key, value);
  },
  removeItem: (key: string) => {
    SecureStore.deleteItemAsync(key);
  },
};

const supabaseUrl = "https://bbrkeceesipzffkdvfpd.supabase.co";
const supabaseAnonKey = SUPABASE_ANON_KEY;

export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
  auth: {
    storage: ExpoSecureStoreAdapter as SupabaseAuthClientOptions["storage"],
    autoRefreshToken: true,
    persistSession: true,
    detectSessionInUrl: false,
  },
});

LoginScreen.ts

    const resetPassword = async (email: string) => {

      const resetPasswordURL = Linking.createURL("resetPassword"); 

      const { data, error } = await supabase.auth.resetPasswordForEmail(email, {
        redirectTo: resetPasswordURL,
      });
    };

Screenshots

inspector

System information

  • React Native: 0.72.3
  • Expo: ^49.0.0
  • Expo Linking: ~5.0.2
  • Supabase: ^2.32.0

AHMED-5G avatar Aug 22 '23 23:08 AHMED-5G

To take advantage of the exchange code route method, you need to set auth > flowType option to pkce for your supabase client

j4w8n avatar Aug 29 '23 08:08 j4w8n

However, the query parameter looks like this: exp://127.0.0.1:8081/--/resetPassword#access_token=123&expires_in=3600&refresh_token=123&token_type=bearer&type=recovery"

Multiple problems here:

  1. As @j4w8n mentioned you need flowtype set to pkce.
  2. For non PKCE flow you need to replace the # with ? to be able to extract it from the query.

Augment this for PKCE flow once you have that enabled. You also need URL polyfill to be installed.

const parsedUrl = url_with_code_as_hashtag.replace("#", "?");
const url = new URL(parsedUrl);
const access_token = url.searchParams.get("access_token");
const refresh_token = url.searchParams.get("refresh_token");

// Handle code exchanges

I'm using Supabase without PKCE with success from the above code.

sannajammeh avatar Sep 06 '23 14:09 sannajammeh

However, the query parameter looks like this: exp://127.0.0.1:8081/--/resetPassword#access_token=123&expires_in=3600&refresh_token=123&token_type=bearer&type=recovery"

Multiple problems here:

  1. As @j4w8n mentioned you need flowtype set to pkce.
  2. For non PKCE flow you need to replace the # with ? to be able to extract it from the query.

Augment this for PKCE flow once you have that enabled. You also need URL polyfill to be installed.

const parsedUrl = url_with_code_as_hashtag.replace("#", "?");
const url = new URL(parsedUrl);
const access_token = url.searchParams.get("access_token");
const refresh_token = url.searchParams.get("refresh_token");

// Handle code exchanges

I'm using Supabase without PKCE with success from the above code.

That is by design. The supabase client, in non-pkce mode, should be handling that scenario automatically.

j4w8n avatar Sep 06 '23 14:09 j4w8n

That is by design. The supabase client, in non-pkce mode, should be handling that scenario automatically.

Yes I'm aware. Not Supabase problem I'm mentioning.

sannajammeh avatar Sep 06 '23 20:09 sannajammeh