0

I am working on a password reset feature for a flutter application. It sends the user an email which sends them to a website which should handle the password reset. However, I am having issues with Supabase session management and I am unable to update the user password.

Flutter function for sending the email.

Future<void> sendPasswordResetEmail(String email, BuildContext context) async {
  try {
    final response = await Supabase.instance.client.auth.resetPasswordForEmail(
      email,
      redirectTo: 'https://mywebsite.co.uk/reset-password',
    );
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('Password reset email sent successfully', textAlign: TextAlign.center,),
        backgroundColor: const Color.fromARGB(255, 52, 157, 44),
      ),
    );
  } catch (e) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('Failed to send password reset email: ${e.toString()}', textAlign: TextAlign.center,),
        backgroundColor: Colors.red,
      ),
    );
  }
}

The Button link that the email takes to

            <div style="text-align: center;">
                 <a 
                    href="{{ .ConfirmationURL }}#token={{ .Token }}&token_hash={{ .TokenHash }}&email={{ .Email }}" 
                    class="button"
                >
                    Reset Password
                </a>
            </div>

The inital part of the password reset (Assuming the error lies here)

  const [passwords, setPasswords] = useState({ password: '', confirmPassword: '' });
  const [message, setMessage] = useState({ type: '', text: '' });
  const [isLoading, setIsLoading] = useState(false);
  const [session, setSession] = useState(null);
  const [showPassword, setShowPassword] = useState(false);
  const [showConfirmPassword, setShowConfirmPassword] = useState(false);
  const [email, setEmail] = useState('');

  useEffect(() => {
    const searchParams = new URLSearchParams(window.location.search);
    const hashParams = new URLSearchParams(window.location.hash.substring(1));

    const searchError = searchParams.get('error');
    const hashError = hashParams.get('error');
    const errorDescription = searchParams.get('error_description') || hashParams.get('error_description');

    if (searchError || hashError) {
      setMessage({
        type: 'error',
        text: errorDescription || 'Invalid or expired reset link',
      });
      return;
    }

    const token = hashParams.get('token');
    const tokenHash = hashParams.get('token_hash');
    const hashEmail = hashParams.get('email');

    console.log('token:', token);
    console.log('token hash:', tokenHash);
    console.log('email:', hashEmail);

    if (!token || !tokenHash) {
      setMessage({
        type: 'error',
        text: 'Invalid reset link - missing required parameters',
      });
      return;
    }

    if (hashEmail) {
      setEmail(hashEmail);
    }

    // Immediately verify the OTP token for recovery
    const verifyRecoveryToken = async () => {
      const { data, error } = await supabase.auth.verifyOtp({
        email: hashEmail,
        token: token,
        type: 'recovery',
      });

      if (error) {
        console.error('Verification error:', error);
        setMessage({
          type: 'error',
          text: error.message || 'Invalid or expired reset link.',
        });
      } else {
        console.log('Verified session:', data);
        setSession(data);
        setMessage({
          type: 'success',
          text: 'Reset link verified. Please set your new password.',
        });
      }
    };

    verifyRecoveryToken();
  }, []);

The actual sending the request to the server.

  const handlePasswordReset = async (e) => {
    e.preventDefault();

    if (!session) {
      setMessage({
        type: 'error',
        text: 'No active session. Please request a new password reset.',
      });
      return;
    }

    setIsLoading(true);

    // Validate passwords before proceeding
    if (passwords.password !== passwords.confirmPassword) {
      setMessage({
        type: 'error',
        text: 'Passwords do not match.',
      });
      setIsLoading(false);
      return;
    }

    if (passwords.password.length < 6) {
      setMessage({
        type: 'error',
        text: 'Password must be at least 6 characters long.',
      });
      setIsLoading(false);
      return;
    }

    try {
      // Update the password using the verified session
      const { error: updateError } = await supabase.auth.updateUser({
        password: passwords.password,
      });

      if (updateError) throw updateError;

      setMessage({
        type: 'success',
        text: 'Password updated successfully!',
      });

      // Clear the form
      setPasswords({ password: '', confirmPassword: '' });

      // Redirect after success (adjust the URL as needed)
      setTimeout(() => {
        window.location.href = 'invoiceup://';
      }, 2000);
    } catch (error) {
      console.error('Password update error:', error);
      setMessage({
        type: 'error',
        text: error.message || 'Failed to update password. Please try again.',
      });
    } finally {
      setIsLoading(false);
    }
  };

EDIT 1: I seem to be getting an error when trying to access supabase with my client

{"message":"No API key found in request","hint":"No `apikey` request header or url param was found."}

This is my code for it

import { createClient } from '@supabase/supabase-js';

const supabaseUrl = 'https://xxxxxxxxxxxxxxx.supabase.co';
const supabaseAnonKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

// Initialize Supabase client with enhanced auth configuration
export const supabase = createClient(supabaseUrl, supabaseAnonKey);

I also saw someone say it must be due to supabase allowed sites however the https:// is included therefore it should work. I also have allowed all pages of my site to be allowed auth data.
https://*.mysite.co.uk/*
added in. the url settings of my project

I tried to send myself the password reset email. It sent correctly, the link looks something like this

https://www.mywebsite.co.uk/reset-password?code=9067907a-xxxx-4603-xxxx-e7241b9d3230#token=444555&token_hash=pkce_f3fc77a38dc132a94641a1ad0bd7051baa9addea9f85xxxxxxx&email=myemail%40outlook.com

How the variables are: token: 444555 token hash: pkce_f3fc77a38dc132a94641a1ad0bd7051baa9addea9f857xxxxxxxxxxxx e9192ac6.0eb2f27f.js:1 email: [email protected]

Instead of a successful sign in i got errors:

Failed to load resource: the server responded with a status of 403 ()Understand this errorAI

** Failed to load resource: the server responded with a status of 403 ()Understand this errorAI Verification error: AuthApiError: Token has expired or is invalid**

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.