0

I'm trying to reset the password of an already registered user, which is currently not authenticated. I wrote a simple Python script which is based on:

  • defining a supabase client object
  • sending a reset link to the inserted email
  • verifying the token from the received link
  • updating the user password

Here is the code:

import os
from supabase import create_client, Client
from dotenv import load_dotenv

load_dotenv()

# method to return the supabase client object from the .env file
# the object will be used to carry out authentication requests 
def get_supabase_object() -> Client:
    url: str = os.environ["SUPABASE_URL"]
    key: str = os.environ["SUPABASE_KEY"]
    supabase: Client = create_client(url, key)
    return supabase

def send_reset_link(supabase: Client):
    try:
        email = input("Please insert your email\n")

        resp = supabase.auth.reset_password_for_email(
            email, 
        )

        print("RESP=")
        print(resp)
        print("\nIf your email is already registered, you will receive a password reset email! Please check your inbox.\n")
    except Exception as e:
        print("Failed to send reset email: ", str(e), "\n")


def update_password(supabase: Client):
    try:
        link = input("Please paste the link you received via email\n")
        email = input("Please insert your email\n")
        password = input("Please insert your new password\n")

        # Extract token from the link
        token = link.split("token=")[1].split("&type")[0]
        print("TOKEN = ",token)
        
        if not token:
            raise ValueError("Invalid link. No token found.")

        # Use the token to sign in temporarily (session for recovery)
        resp_1 = supabase.auth.verify_otp({
            "email": email,
            "type": "recovery",
            "token": token,
        })
        print("RESP_1=")
        print(resp_1)
        print("\n")

        # Now update the password
        resp_2 = supabase.auth.update_user({
            "password": password
        })
        print("RESP_2=")
        print(resp_2)
        print("\n")

        print("Password updated successfully\n")

    except Exception as e:
        print("Failed to update password: ", str(e), "\n")


supabase: Client = get_supabase_object()
print(supabase)
print("\n\n")

send_reset_link(supabase)
update_password(supabase)

Once I run the code, I receive a reset link in this format:

"https://ABC.supabase.co/auth/v1/verify?token=XYZ&type=recovery&redirect_to=http://localhost:3000"

Using print() logging, I verified that the token was correctly extracted. However, after having inserted the new password, I get this exception:

Please insert your new password
****** (censored)
TOKEN =  ***************************************************** (censored)
Failed to update password:  Token has expired or is invalid

What I am missing?

1 Answer 1

2

You should update your email template to use a token_hash instead and use that to verify the otp.

<h2>Password Reset</h2>

<p>We're sorry to hear that you're having trouble accessing your account. To reset your password and regain access, please paste the token hash below into your terminal:</p>

<p>Token Hash: {{ .TokenHash }}</p>

And then in your Python code ingest the token hash:

resp_1 = supabase.auth.verify_otp({
  "type": "recovery",
  "token_hash": token,
})
Sign up to request clarification or add additional context in comments.

Comments

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.