FastAPI बैकएंड डेवलपमेंट बूटकैंप · पाठ

python-jose के साथ JWT पर हस्ताक्षर और सत्यापन

दावों, समय-सीमा और ऑडियंस सत्यापन के साथ JWT को एनकोड और डीकोड कीजिए तथा मार्गों को छेड़छाड़ से सुरक्षित रखिए।

पाठ 2, कुल 4 में से13 चरण

python-jose के साथ JWT पर हस्ताक्षर और सत्यापन, CoddyKit पर FastAPI बैकएंड डेवलपमेंट बूटकैंप का एक निःशुल्क पाठ है। यह 4 में से 2वाँ पाठ है। इस अध्ययन पथ के 3 तक कोई भी पाठ पूरा पढ़ना निःशुल्क है — इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ व्यावहारिक अभ्यास भी उपलब्ध कराता है। यह FastAPI बैकएंड डेवलपमेंट बूटकैंप सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

स्टेटलेस प्रमाणीकरण के लिए JWT क्यों

JWT (JSON Web Token) एक संक्षिप्त, हस्ताक्षरित टोकन है, जिसमें उपयोगकर्ता के बारे में दावे होते हैं। आपका FastAPI ऐप लॉगिन पर JWT जारी करने के बाद, क्लाइंट उसे हर अनुरोध में वापस भेजता है और आप सत्र भंडार को छुए बिना उसका सत्यापन करते हैं।

  • स्टेटलेस — सर्वर सत्र संग्रहीत नहीं करता; हस्ताक्षर प्रामाणिकता सिद्ध करता है।
  • छेड़छाड़ का पता चल जाता है — पेलोड में कोई भी बदलाव हस्ताक्षर को अमान्य कर देता है।
  • पोर्टेबल — समान गुप्त कुंजी या सार्वजनिक कुंजी साझा करने वाली सेवाओं में वही टोकन काम करता है।

इस पाठ में हम दावों, समाप्ति और ऑडियंस सत्यापन के साथ टोकन को encode (हस्ताक्षरित) और decode (सत्यापित) करने के लिए python-jose का उपयोग करते हैं।

JWT की संरचना

JWT के तीन Base64URL भाग होते हैं, जिन्हें बिंदुओं से जोड़ा जाता है: header.payload.signature।

  • हेडर — एल्गोरिदम और टोकन का प्रकार, जैसे {"alg": "HS256", "typ": "JWT"}।
  • पेलोड — दावे (डेटा), जैसे sub, exp, aud।
  • हस्ताक्षर — हेडर और पेलोड का कुंजी-आधारित हैश, जो सिद्ध करता है कि टोकन बदला नहीं गया।

आप सबसे अधिक जिन मानक (पंजीकृत) दावों का उपयोग करेंगे: sub (विषय/उपयोगकर्ता आईडी), exp (समाप्ति), iat (जारी करने का समय), aud (ऑडियंस), iss (जारीकर्ता)। पेलोड केवल एन्कोड किया जाता है, एन्क्रिप्ट नहीं, इसलिए उसमें पासवर्ड जैसे गुप्त डेटा कभी न रखें।

python-jose इंस्टॉल और इंपोर्ट करना

क्रिप्टोग्राफी बैकएंड के साथ python-jose इंस्टॉल करें, ताकि RSA और EC एल्गोरिदम भी काम कर सकें:

  • pip install "python-jose[cryptography]"

जिन दो फ़ंक्शन का आप लगातार उपयोग करेंगे, वे jose.jwt में हैं: हस्ताक्षर करने के लिए jwt.encode(...) और सत्यापित करने के लिए jwt.decode(...)। त्रुटियाँ JWTError की उपश्रेणियों के रूप में उत्पन्न होती हैं, जिससे आप टोकन की सभी समस्याओं को व्यवस्थित रूप से पकड़ सकते हैं।

from jose import jwt
from jose.exceptions import JWTError, ExpiredSignatureError, JWTClaimsError

print("encode:", callable(jwt.encode))
print("decode:", callable(jwt.decode))
print("base error:", issubclass(ExpiredSignatureError, JWTError))

अपना पहला टोकन एन्कोड करना

किसी टोकन पर हस्ताक्षर करने के लिए क्लेम डिक्शनरी, गुप्त कुंजी और एल्गोरिदम दें। सममित हस्ताक्षर के लिए हम HS256 का उपयोग करते हैं, जिसमें वही गुप्त कुंजी हस्ताक्षर करने और सत्यापित करने दोनों के लिए इस्तेमाल होती है।

  • उपयोगकर्ता की आईडी sub में रखें — यह स्ट्रिंग होनी चाहिए।
  • गुप्त कुंजी को लंबी और यादृच्छिक रखें; वास्तविक ऐप में इसे पर्यावरण चर से लोड करें।

परिणाम एक अकेली URL-सुरक्षित स्ट्रिंग होती है, जिसे आप क्लाइंट को वापस दे सकते हैं।

from jose import jwt

SECRET = "a-very-long-random-secret-string-change-me"
ALGO = "HS256"

claims = {"sub": "user-42", "role": "admin"}
token = jwt.encode(claims, SECRET, algorithm=ALGO)
print(token[:40] + "...")
print("dot count:", token.count("."))

डिकोड करना और सत्यापित करना

jwt.decode एक साथ दो काम करता है: यह हस्ताक्षर की जाँच करता है और क्लेम लौटाता है। यदि हस्ताक्षर गलत हो, तो यह डेटा लौटाने के बजाय JWTError उत्पन्न करता है।

  • algorithms=[...] के माध्यम से वही एल्गोरिदम दें जिनसे आपने हस्ताक्षर किया था — केवल टोकन के हेडर में बताए गए एल्गोरिदम पर कभी भरोसा न करें।
  • सफल डिकोड का अर्थ है कि टोकन असली है और उसके साथ छेड़छाड़ नहीं की गई है।

नीचे दिया गया उदाहरण पहले टोकन पर हस्ताक्षर करता है, फिर उसे सत्यापित करके क्लेम वापस पढ़ता है।

from jose import jwt

SECRET = "a-very-long-random-secret-string-change-me"

token = jwt.encode({"sub": "user-42", "role": "admin"}, SECRET, algorithm="HS256")
payload = jwt.decode(token, SECRET, algorithms=["HS256"])
print("sub:", payload["sub"])
print("role:", payload["role"])

छेड़छाड़ का पता लगाना

हस्ताक्षर करने का यही मुख्य उद्देश्य है। यदि कोई हमलावर पेलोड में एक भी अक्षर बदल दे, तो सत्यापन विफल हो जाता है क्योंकि हस्ताक्षर अब मेल नहीं खाता।

  • अनुरोध को 401 Unauthorized के साथ अस्वीकार करने के लिए JWTError को पकड़ें।
  • उत्पादन में कभी भी verify_signature=False के साथ डिकोड न करें — इससे सुरक्षा जाँच पूरी तरह छूट जाती है।

यह कोड एक टोकन को खराब करके दिखाता है कि सत्यापन में त्रुटि कैसे उत्पन्न होती है।

from jose import jwt
from jose.exceptions import JWTError

SECRET = "a-very-long-random-secret-string-change-me"
token = jwt.encode({"sub": "user-42"}, SECRET, algorithm="HS256")

# Tamper: change the last character of the token
tampered = token[:-1] + ("A" if token[-1] != "A" else "B")
try:
    jwt.decode(tampered, SECRET, algorithms=["HS256"])
    print("accepted (BAD)")
except JWTError as e:
    print("rejected tampered token:", type(e).__name__)

exp के साथ समाप्ति जोड़ना

टोकन का जीवनकाल छोटा होना चाहिए। exp क्लेम एक यूनिक्स टाइमस्टैम्प है (युगारंभ से बीते सेकंड, UTC)। python-jose डिकोड करते समय समाप्त हो चुके टोकन को अपने-आप अस्वीकार करता है और ExpiredSignatureError उत्पन्न करता है।

  • समय-क्षेत्र की जानकारी वाले UTC के साथ समाप्ति की गणना करें: datetime.now(timezone.utc) + timedelta(...)।
  • एक्सेस टोकन आम तौर पर 15–30 मिनट के होते हैं; रिफ्रेश टोकन अधिक समय तक चलते हैं।

आप exp के लिए datetime या पूर्णांक दे सकते हैं — jose आपके लिए datetime को टाइमस्टैम्प में बदल देता है।

from datetime import datetime, timedelta, timezone
from jose import jwt

SECRET = "a-very-long-random-secret-string-change-me"
expire = datetime.now(timezone.utc) + timedelta(minutes=30)
claims = {"sub": "user-42", "exp": expire}

token = jwt.encode(claims, SECRET, algorithm="HS256")
payload = jwt.decode(token, SECRET, algorithms=["HS256"])
print("exp claim (unix):", payload["exp"])
print("valid for ~30 min")

समाप्त हो चुके टोकन संभालना

जब टोकन का exp बीते हुए समय में होता है, तो jwt.decode ExpiredSignatureError उत्पन्न करता है (JWTError का एक उपवर्ग)। इसे अलग से संभालें, ताकि आप क्लाइंट को दोबारा लॉगिन करने के बजाय रिफ्रेश करने के लिए कह सकें।

  • पहले ExpiredSignatureError को पकड़ें, फिर सामान्य JWTError को।
  • घड़ी के समय में अंतर के लिए jose थोड़ी डिफ़ॉल्ट छूट लागू करता है; आप इसे options के माध्यम से समायोजित कर सकते हैं।

यहाँ हम जाँच के सक्रिय होने को साबित करने के लिए पहले से समाप्त टोकन जारी करते हैं।

from datetime import datetime, timedelta, timezone
from jose import jwt
from jose.exceptions import ExpiredSignatureError, JWTError

SECRET = "a-very-long-random-secret-string-change-me"
past = datetime.now(timezone.utc) - timedelta(minutes=5)
token = jwt.encode({"sub": "user-42", "exp": past}, SECRET, algorithm="HS256")

try:
    jwt.decode(token, SECRET, algorithms=["HS256"])
except ExpiredSignatureError:
    print("token expired -> ask client to refresh")
except JWTError:
    print("other token error")

aud के साथ ऑडियंस सत्यापन

aud (ऑडियंस) क्लेम बताता है कि टोकन किसके लिए है — जैसे आपका एपीआई। यदि आप इसे एन्कोड करते समय सेट करते हैं, तो डिकोड करते समय मिलान करता हुआ audience= देना आवश्यक है, वरना jose JWTClaimsError उत्पन्न करता है।

  • यह एक सेवा के लिए बनाए गए टोकन को दूसरी सेवा के विरुद्ध दोबारा इस्तेमाल होने से रोकता है।
  • यदि आप audience= छोड़ देते हैं, लेकिन टोकन में aud मौजूद है, तो सत्यापन विफल हो जाता है — इसे स्पष्ट रूप से दें।

उदाहरण ऑडियंस के साथ हस्ताक्षर करता है और डिकोड करते समय उसका सत्यापन करता है।

from jose import jwt
from jose.exceptions import JWTClaimsError

SECRET = "a-very-long-random-secret-string-change-me"
token = jwt.encode(
    {"sub": "user-42", "aud": "fastapi-bootcamp-api"},
    SECRET, algorithm="HS256",
)

payload = jwt.decode(token, SECRET, algorithms=["HS256"], audience="fastapi-bootcamp-api")
print("aud ok:", payload["aud"])

try:
    jwt.decode(token, SECRET, algorithms=["HS256"], audience="some-other-api")
except JWTClaimsError as e:
    print("wrong audience rejected:", type(e).__name__)

दोबारा इस्तेमाल योग्य टोकन सहायक

वास्तविक प्रशिक्षण-शिविर परियोजना में आप हस्ताक्षर करने और सत्यापित करने की प्रक्रिया को छोटे सहायक कार्यों में लपेटते हैं, ताकि मार्ग साफ-सुथरे रहें। मानक क्लेम — sub, exp, iat, aud, iss — एक ही स्थान पर रखें।

  • create_access_token क्लेम बनाता है और हस्ताक्षर करता है।
  • verify_token सभी सत्यापनों के साथ डिकोड करता है और पेलोड लौटाता है या त्रुटि उत्पन्न करता है।

इस शुद्ध-Python मॉड्यूल में FastAPI का कोई आयात नहीं है, इसलिए इसे अपने-आप इकाई-परीक्षण करना आसान है।

from datetime import datetime, timedelta, timezone
from jose import jwt
from jose.exceptions import JWTError

SECRET = "a-very-long-random-secret-string-change-me"
ALGO, AUD, ISS = "HS256", "fastapi-bootcamp-api", "auth-service"

def create_access_token(sub, minutes=30):
    now = datetime.now(timezone.utc)
    claims = {"sub": sub, "iat": now, "exp": now + timedelta(minutes=minutes),
              "aud": AUD, "iss": ISS}
    return jwt.encode(claims, SECRET, algorithm=ALGO)

def verify_token(token):
    return jwt.decode(token, SECRET, algorithms=[ALGO], audience=AUD, issuer=ISS)

t = create_access_token("user-42")
print("verified sub:", verify_token(t)["sub"])

FastAPI मार्ग को सुरक्षित करना

FastAPI में आप सत्यापन को एक निर्भरता में जोड़ते हैं। OAuth2PasswordBearer Authorization: Bearer ... हेडर से टोकन निकालता है, फिर आपकी निर्भरता उसे सत्यापित करके वर्तमान उपयोगकर्ता लौटाती है — या HTTPException(401) उत्पन्न करती है।

  • Depends(get_current_user) घोषित करने वाला कोई भी मार्ग अब सुरक्षित है।
  • JWTError को उचित 401 में बदलें, ताकि छेड़छाड़ किए गए या समाप्त हो चुके टोकन सही स्थिति के साथ अस्वीकार किए जाएँ।

यह फ्रेमवर्क का कोड है, इसलिए यह अकेले चलने वाले जाँच-कार्यक्रम में नहीं, बल्कि सर्वर के भीतर चलता है।

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import jwt
from jose.exceptions import JWTError

app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
SECRET, ALGO, AUD = "change-me", "HS256", "fastapi-bootcamp-api"

def get_current_user(token: str = Depends(oauth2_scheme)):
    creds_exc = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET, algorithms=[ALGO], audience=AUD)
    except JWTError:
        raise creds_exc
    user_id = payload.get("sub")
    if user_id is None:
        raise creds_exc
    return user_id

@app.get("/me")
def read_me(user_id: str = Depends(get_current_user)):
    return {"user_id": user_id}

त्वरित जाँच: ऑडियंस सत्यापन

आप aud="fastapi-bootcamp-api" के साथ टोकन पर हस्ताक्षर करते हैं। आपके सहकर्मी का डिकोड कॉल कभी-कभी नए जारी किए गए और बिना छेड़छाड़ वाले टोकन के लिए भी JWTClaimsError उत्पन्न करता है। इसका सबसे संभावित कारण क्या है?

पुनरावृत्ति: JWT पर हस्ताक्षर करना और सत्यापित करना

अब आप python-jose के साथ शुरू से अंत तक JWT बना और सत्यापित कर सकते हैं:

  • jwt.encode(claims, secret, algorithm="HS256") के साथ क्लेम को एन्कोड करें; sub को स्ट्रिंग रखें और गुप्त कुंजी को पर्यावरण चर में रखें।
  • jwt.decode(token, secret, algorithms=[...]) के साथ डिकोड करें और एल्गोरिदम सूची को हमेशा निश्चित रखें।
  • छेड़छाड़ से हस्ताक्षर टूट जाता है और JWTError उत्पन्न होता है — 401 के साथ अस्वीकार करें।
  • exp के माध्यम से समाप्ति होने पर अपने-आप ExpiredSignatureError उत्पन्न होता है; रिफ्रेश शुरू करने के लिए इसे संभालें।
  • aud के माध्यम से दी गई ऑडियंस का डिकोड करते समय audience= से मिलान होना चाहिए, वरना JWTClaimsError प्राप्त होता है।
  • FastAPI में Depends(get_current_user) निर्भरता के भीतर सत्यापन करें और त्रुटियों को HTTPException(401) में बदलें।

अगला विषय: रिफ्रेश टोकन और बदलती हुई हस्ताक्षर कुंजियाँ।

शुरुआत निःशुल्क

एआई शिक्षक के साथ FastAPI बैकएंड डेवलपमेंट बूटकैंप सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
21
पाठ
84

अक्सर पूछे जाने वाले प्रश्न

क्या “python-jose के साथ JWT पर हस्ताक्षर और सत्यापन” पाठ निःशुल्क है?

हाँ — FastAPI बैकएंड डेवलपमेंट बूटकैंप अध्ययन पथ के 3 तक कोई भी पाठ, जिसमें “python-jose के साथ JWT पर हस्ताक्षर और सत्यापन” भी शामिल है, यहाँ वेब पर पूरा पढ़ना निःशुल्क है। इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ इंटरैक्टिव अभ्यास भी उपलब्ध कराता है। FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“python-jose के साथ JWT पर हस्ताक्षर और सत्यापन” में मैं क्या सीखूँगा?

दावों, समय-सीमा और ऑडियंस सत्यापन के साथ JWT को एनकोड और डीकोड कीजिए तथा मार्गों को छेड़छाड़ से सुरक्षित रखिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ FastAPI बैकएंड डेवलपमेंट बूटकैंप का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या FastAPI बैकएंड डेवलपमेंट बूटकैंप शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर FastAPI बैकएंड डेवलपमेंट बूटकैंप शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 2वाँ पाठ है।

“python-jose के साथ JWT पर हस्ताक्षर और सत्यापन” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. OAuth2 पासवर्ड प्रवाह और टोकन जारी करना
  2. python-jose के साथ JWT पर हस्ताक्षर और सत्यापन
  3. रिफ्रेश टोकन और टोकन रोटेशन
  4. स्कोप-आधारित प्राधिकरण और भूमिका गार्ड
← FastAPI बैकएंड डेवलपमेंट बूटकैंप पर वापस जाएँ