2025, Oct 17 23:31

dj-rest-auth में साइन-अप पर JWT HTTP-only कुकीज़ कैसे सेट करें

गाइड: Django REST Framework में dj-rest-auth/django-allauth के साथ साइन-अप पर JWT को HTTP-only कुकीज़ में सेट करें, ताकि लॉगिन जैसा ही ऑथ फ्लो मिले.

जब आप Django REST Framework में dj-rest-auth और django-allauth के साथ JWT का उपयोग करते हुए प्रमाणीकरण जोड़ते हैं, तो टोकन स्टोरेज के लिए अक्सर HTTP-only कुकीज़ पर भरोसा किया जाता है। बिल्ट-इन लॉगिन एंडपॉइंट पहले से यही करता है—access और refresh टोकन के लिए कुकीज़ सेट करता है। पर रजिस्ट्रेशन के समय एक अंतर दिखता है: डिफ़ॉल्ट रजिस्ट्रेशन एंडपॉइंट टोकन सिर्फ response body में लौटाता है और JWT कुकीज़ सेट नहीं करता। नीचे दिया गया संक्षिप्त मार्गदर्शक रजिस्ट्रेशन को लॉगिन के अनुरूप लाता है, ताकि दोनों ही HTTP-only कुकीज़ के माध्यम से JWT जारी करें।

कहाँ गड़बड़ होती है

dj_rest_auth का लॉगिन एंडपॉइंट अपने आप JWTs को HTTP-only कुकीज़ में सेट करता है और साथ ही access टोकन को response body में भी लौटाता है। इसके उलट, रजिस्ट्रेशन एंडपॉइंट access और refresh टोकन केवल response body में देता है और उन्हें कुकीज़ के रूप में नहीं जोड़ता। अगर आपका फ्रंटएंड साइन-अप के बाद भी वही कुकी-आधारित टोकन फ्लो चाहता है जो साइन-इन के बाद मिलता है, तो यह असंगति एक वास्तविक इंटीग्रेशन समस्या बन जाती है।

मिसमैच दिखाने वाला सबसे छोटा उदाहरण

स्टॉक रजिस्ट्रेशन व्यू का इस्तेमाल करने पर ऊपर बताई गई ही स्थिति मिलती है — टोकन सिर्फ response body में आते हैं, कुकीज़ में नहीं।

# urls.py
from django.urls import path
from dj_rest_auth.registration.views import RegisterView as SignupBaseView
urlpatterns = [
    path("auth/register/", SignupBaseView.as_view(), name="register"),
]

ऐसा क्यों होता है

रजिस्ट्रेशन व्यू में वह कुकी-सेट करने वाली लॉजिक है ही नहीं जो लॉगिन व्यू में मौजूद है। साफ तौर पर: RegisterView JWT कुकीज़ सेट नहीं करता; LoginView करता है। यही अंतर पूरी विसंगति की वजह है।

रजिस्ट्रेशन से भी HTTP-only कुकीज़ कैसे सेट करवाएँ

रजिस्ट्रेशन व्यू को बढ़ाएँ और सफल साइन-अप पर कुकीज़ स्पष्ट रूप से सेट करें। तरीका सरल है: पैरेंट create() को कॉल करें, 201 रिस्पॉन्स देखें, response payload से access और refresh टोकन पढ़ें, और set_jwt_cookies लागू करें।

# views.py
from dj_rest_auth.registration.views import RegisterView
from dj_rest_auth.jwt_auth import set_jwt_cookies as bind_jwt_cookies
from rest_framework import status as http_status
class SignupCookieView(RegisterView):
    def create(self, request, *args, **kwargs):
        reply = super().create(request, *args, **kwargs)
        if reply.status_code == http_status.HTTP_201_CREATED:
            token_access = reply.data.get("access")
            token_refresh = reply.data.get("refresh")
            if token_access and token_refresh:
                bind_jwt_cookies(reply, token_access, token_refresh)
        return reply
# urls.py
from django.urls import path
from .views import SignupCookieView
urlpatterns = [
    path("auth/register/", SignupCookieView.as_view(), name="signup_with_cookies"),
]

“डिफ़ॉल्ट रूप से ऐसा क्यों नहीं?” पर एक छोटा नोट

व्यावहारिक उत्तर यही है कि रजिस्ट्रेशन व्यू में वह कुकी-सेटिंग वाला मार्ग शामिल नहीं है जिसे लॉगिन व्यू लागू करता है। रजिस्ट्रेशन और लॉगिन फ्लो के बीच किसी अप्रत्यक्ष जोड़ पर निर्भर रहने के बजाय, यह तरीका व्यवहार को स्पष्ट बनाता है—रजिस्ट्रेशन व्यू को ओवरराइड करके कुकीज़ आप खुद सेट करते हैं।

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

साइन-अप और साइन-इन फ्लो में स्थिरता रखने से क्लाइंट पर किनारी केस घटते हैं और आप एंड-टू-एंड कुकी-आधारित JWT हैंडलिंग मॉडल के प्रति सुसंगत रहते हैं। यदि आपकी एप्लिकेशन रणनीति टोकन को HTTP-only कुकीज़ में रखना है, तो रजिस्ट्रेशन को लॉगिन के अनुरूप करने से प्रथम-बार उपयोगकर्ताओं के लिए अलग तरह की विशेष लॉजिक की जरूरत नहीं पड़ती और refresh टोकन को केवल वहीं सीमित रखा जाता है जहाँ आप चाहते हैं।

समापन

यूज़र यात्रा को एक-सा रखें: लॉगिन और रजिस्ट्रेशन—दोनों के बाद—क्लाइंट को वही ऑथेंटिकेशन स्थिति मिलनी चाहिए। dj-rest-auth और django-allauth के साथ, इसका अर्थ है रजिस्ट्रेशन व्यू को इस तरह बढ़ाना कि सफल अकाउंट निर्माण पर वह JWT कुकीज़ सेट करे। बदलाव छोटा है, लेकिन यह क्लाइंट कोड में अनावश्यक घर्षण हटाता है और आपके एंडपॉइंट्स को चुने हुए कुकी-आधारित JWT दृष्टिकोण के अनुरूप लाता है।

यह लेख StackOverflow पर एक प्रश्न (द्वारा Sebastian Power) और Razia Khan के उत्तर पर आधारित है।