2025, Oct 21 09:33

Python से Supabase पासवर्ड रीसेट करें: token_hash से verify_otp

Supabase पासवर्ड रीसेट में Token has expired or is invalid त्रुटि मिल रही है? Python में token की जगह token_hash के साथ verify_otp करें और सुरक्षित रूप से पासवर्ड अपडेट करें.

Python स्क्रिप्ट से Supabase उपयोगकर्ता का पासवर्ड रीसेट करना ऊपर से आसान लगता है, लेकिन “Token has expired or is invalid” जैसी त्रुटि पर रुक जाना भी उतना ही आम है। पेच सूक्ष्म है: रीसेट लिंक में दिख रहे token को सीधे सत्यापन के लिए देना इस फ्लो में काम नहीं करता। समाधान है कि ईमेल टेम्पलेट में token_hash शामिल करें और उसे verify_otp में पास करें।

समस्या की रूपरेखा

स्क्रिप्ट Supabase क्लाइंट इनिशियलाइज़ करती है, पासवर्ड रीसेट ईमेल भेजती है, लिंक से टोकन निकालती है, उसे वेरिफ़ाई करती है और फिर पासवर्ड अपडेट करती है। लिंक इस तरह आता है: https://ABC.supabase.co/auth/v1/verify?token=XYZ&type=recovery&redirect_to=http://localhost:3000, टोकन सही तरह से पार्स हो जाता है, फिर भी verify_otp “Token has expired or is invalid” फेंक देता है।

पुनरुत्पादित करने योग्य उदाहरण

नीचे दिया गया Python कोड पूरा प्रवाह दिखाता है—प्राप्त URL से टोकन निकालना और उसे recovery OTP के रूप में वेरिफ़ाई करने की कोशिश सहित।

import os
from supabase import create_client, Client
from dotenv import load_dotenv
load_dotenv()
# परिवेश से Supabase क्लाइंट प्रारंभ करें
# अपेक्षित है कि परिवेश में SUPABASE_URL और SUPABASE_KEY मौजूद हों
def build_client() -> Client:
    api_url: str = os.environ["SUPABASE_URL"]
    anon_key: str = os.environ["SUPABASE_KEY"]
    sb: Client = create_client(api_url, anon_key)
    return sb
def dispatch_reset_link(sb: Client):
    try:
        user_email = input("Please insert your email\n")
        resp = sb.auth.reset_password_for_email(
            user_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 exc:
        print("Failed to send reset email: ", str(exc), "\n")
def change_secret(sb: Client):
    try:
        link_raw = input("Please paste the link you received via email\n")
        email_input = input("Please insert your email\n")
        new_pass = input("Please insert your new password\n")
        # URL से टोकन निकालें
        parsed_token = link_raw.split("token=")[1].split("&type")[0]
        print("TOKEN = ", parsed_token)
        if not parsed_token:
            raise ValueError("Invalid link. No token found.")
        # URL के टोकन से recovery OTP सत्यापित करें
        resp_verify = sb.auth.verify_otp({
            "email": email_input,
            "type": "recovery",
            "token": parsed_token,
        })
        print("RESP_1=")
        print(resp_verify)
        print("\n")
        # प्रमाणित रिकवरी सत्र के लिए पासवर्ड अपडेट करें
        resp_update = sb.auth.update_user({
            "password": new_pass
        })
        print("RESP_2=")
        print(resp_update)
        print("\n")
        print("Password updated successfully\n")
    except Exception as exc:
        print("Failed to update password: ", str(exc), "\n")
sb_client: Client = build_client()
print(sb_client)
print("\n\n")
dispatch_reset_link(sb_client)
change_secret(sb_client)

वेरिफ़िकेशन क्यों विफल होता है

रिकवरी URL में token पैरामीटर होता है, लेकिन उसी मान को सीधे verify_otp में देने पर “Token has expired or is invalid” त्रुटि मिलती है। इस फ्लो में सही इनपुट token नहीं, बल्कि token_hash है। यदि आप URL वाले token को verify_otp में भेजेंगे, तो वेरिफ़िकेशन विफल रहेगा और आप पासवर्ड अपडेट चरण तक नहीं पहुंच पाएंगे।

समाधान

पहले ईमेल टेम्पलेट को इस तरह बदलें कि उसमें token hash शामिल हो। फिर उस token hash को पढ़कर verify_otp में token_hash फ़ील्ड के रूप में पास करें।

<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>

अपने Python कोड में, token_hash को इनपुट लें और type को recovery सेट करके verify_otp में इस्तेमाल करें।

resp_1 = sb_client.auth.verify_otp({
  "type": "recovery",
  "token_hash": token_input,
})

इसे ऊपर वाली स्क्रिप्ट में लगाते हुए, URL टोकन पार्स करने के बजाय token hash के लिए इनपुट लें, और पासवर्ड अपडेट कॉल को यथावत रखें।

import os
from supabase import create_client, Client
from dotenv import load_dotenv
load_dotenv()
def build_client() -> Client:
    api_url: str = os.environ["SUPABASE_URL"]
    anon_key: str = os.environ["SUPABASE_KEY"]
    sb: Client = create_client(api_url, anon_key)
    return sb
def dispatch_reset_link(sb: Client):
    try:
        user_email = input("Please insert your email\n")
        resp = sb.auth.reset_password_for_email(user_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 exc:
        print("Failed to send reset email: ", str(exc), "\n")
def change_secret(sb: Client):
    try:
        hashed_token = input("Please paste the token hash you received via email\n")
        new_pass = input("Please insert your new password\n")
        # token_hash का उपयोग करके रिकवरी सत्यापित करें
        resp_verify = sb.auth.verify_otp({
            "type": "recovery",
            "token_hash": hashed_token,
        })
        print("RESP_1=")
        print(resp_verify)
        print("\n")
        # पासवर्ड अपडेट करें
        resp_update = sb.auth.update_user({
            "password": new_pass
        })
        print("RESP_2=")
        print(resp_update)
        print("\n")
        print("Password updated successfully\n")
    except Exception as exc:
        print("Failed to update password: ", str(exc), "\n")
sb_client: Client = build_client()
print(sb_client)
print("\n\n")
dispatch_reset_link(sb_client)
change_secret(sb_client)

यह क्यों मायने रखता है

पासवर्ड रिकवरी फ्लो बनाते समय, बैकएंड की अपेक्षा और आपके द्वारा भेजे गए डेटा में छोटी-सी असंगति भी उलझाऊ त्रुटियाँ और असफल रीसेट पैदा कर सकती है। token_hash का उपयोग करने से वेरिफ़िकेशन वही टोकन इस्तेमाल करता है जिसे ईमेल में दिखाने की सलाह दी जाती है, जिससे प्रक्रिया CLI-शैली की स्क्रिप्ट और उन कस्टम UI दोनों में भरोसेमंद बनती है जो उपयोगकर्ता से इनपुट लेते हैं।

मुख्य बातें

यदि आप रिकवरी URL से token पार्स करने के बाद भी “Token has expired or is invalid” देख रहे हैं, तो token पास करना बंद करें और token_hash पर स्विच करें। पासवर्ड रीसेट ईमेल में token hash दिखाएँ और verify_otp में type को recovery रखते हुए उसी token_hash से वेरिफ़ाई करें। सफल वेरिफ़िकेशन के बाद, नया पासवर्ड सेट करने के लिए update_user चलाएँ।

यह लेख StackOverflow पर एक प्रश्न (लेखक: eljamba) और Andrew Smith द्वारा दिए गए उत्तर पर आधारित है।