Next.js, OpenID4VP, और ISO mDoc का उपयोग करके शुरुआत से डिजिटल क्रेडेंशियल वेरिफ़ायर बनाना सीखें। यह चरण-दर-चरण डेवलपर गाइड दिखाता है कि एक ऐसा वेरिफ़ायर कैसे बनाया जाए जो मोबाइल ड्राइविंग लाइसेंस और अन्य डिजिटल क्रेडेंशियल का अनुरोध, प्राप्त और मान्य कर
Amine
Created: August 20, 2025
Updated: August 21, 2025
See the original blog version in English here.
ऑनलाइन पहचान साबित करना एक लगातार चुनौती बनी हुई है, जिसके कारण हम पासवर्ड पर निर्भर रहते हैं और असुरक्षित चैनलों पर संवेदनशील दस्तावेज़ साझा करते हैं। इसने व्यवसायों के लिए पहचान सत्यापन को एक धीमी, महंगी और धोखाधड़ी-प्रवण प्रक्रिया बना दिया है। डिजिटल क्रेडेंशियल एक नया दृष्टिकोण प्रदान करते हैं, जो उपयोगकर्ताओं को उनके डेटा का नियंत्रण वापस देते हैं। वे एक भौतिक वॉलेट के डिजिटल समकक्ष हैं, जिसमें ड्राइविंग लाइसेंस से लेकर विश्वविद्यालय की डिग्री तक सब कुछ होता है, लेकिन क्रिप्टोग्राफ़िक रूप से सुरक्षित, गोपनीयता-संरक्षित और तुरंत सत्यापन योग्य होने के अतिरिक्त लाभों के साथ।
यह गाइड डेवलपर्स को डिजिटल क्रेडेंशियल के लिए एक वेरिफ़ायर बनाने के लिए एक व्यावहारिक, चरण-दर-चरण ट्यूटोरियल प्रदान करता है। हालाँकि मानक मौजूद हैं, लेकिन उन्हें लागू करने के बारे में बहुत कम मार्गदर्शन है। यह ट्यूटोरियल उस कमी को पूरा करता है, यह दिखाता है कि ब्राउज़र के नेटिव डिजिटल क्रेडेंशियल API, प्रेजेंटेशन प्रोटोकॉल के लिए OpenID4VP और क्रेडेंशियल प्रारूप के रूप में ISO mDoc (जैसे, मोबाइल ड्राइविंग लाइसेंस) का उपयोग करके एक वेरिफ़ायर कैसे बनाया जाए।
अंतिम परिणाम एक सरल लेकिन कार्यात्मक Next.js एप्लिकेशन होगा जो एक संगत मोबाइल वॉलेट से एक डिजिटल क्रेडेंशियल का अनुरोध, प्राप्त और सत्यापित कर सकता है।
यहाँ अंतिम एप्लिकेशन का एक त्वरित अवलोकन है। इस प्रक्रिया में चार मुख्य चरण शामिल हैं:
चरण 1: प्रारंभिक पृष्ठ उपयोगकर्ता प्रारंभिक पृष्ठ पर आता है और प्रक्रिया शुरू करने के लिए "डिजिटल पहचान के साथ सत्यापित करें" पर क्लिक करता है।
चरण 2: ट्रस्ट प्रॉम्प्ट ब्राउज़र उपयोगकर्ता से विश्वास के लिए पूछता है। उपयोगकर्ता आगे बढ़ने के लिए "जारी रखें" पर क्लिक करता है।
चरण 3: QR कोड स्कैन एक QR कोड प्रदर्शित होता है, जिसे उपयोगकर्ता अपने संगत वॉलेट एप्लिकेशन के साथ स्कैन करता है।
चरण 4: डीकोडेड क्रेडेंशियल सफल सत्यापन के बाद, एप्लिकेशन डीकोडेड क्रेडेंशियल डेटा प्रदर्शित करता है।
Recent Articles
डिजिटल क्रेडेंशियल के पीछे का जादू एक सरल लेकिन शक्तिशाली "ट्रस्ट ट्रायंगल" मॉडल में निहित है जिसमें तीन प्रमुख खिलाड़ी शामिल हैं:
जब कोई उपयोगकर्ता किसी सेवा तक पहुँचना चाहता है, तो वे अपने वॉलेट से क्रेडेंशियल प्रस्तुत करते हैं। वेरिफ़ायर तब सीधे मूल जारीकर्ता से संपर्क किए बिना तुरंत उसकी प्रामाणिकता की जाँच कर सकता है।
इस विकेंद्रीकृत पहचान पारिस्थितिकी तंत्र के फलने-फूलने के लिए, वेरिफ़ायर की भूमिका बिल्कुल महत्वपूर्ण है। वे इस नए विश्वास बुनियादी ढाँचे के द्वारपाल हैं, जो क्रेडेंशियल का उपभोग करते हैं और उन्हें वास्तविक दुनिया में उपयोगी बनाते हैं। जैसा कि नीचे दिए गए चित्र में दिखाया गया है, एक वेरिफ़ायर धारक से क्रेडेंशियल का अनुरोध, प्राप्त और सत्यापन करके ट्रस्ट ट्रायंगल को पूरा करता है।
यदि आप एक डेवलपर हैं, तो यह सत्यापन करने के लिए एक सेवा का निर्माण सुरक्षित और उपयोगकर्ता-केंद्रित अनुप्रयोगों की अगली पीढ़ी के लिए एक मौलिक कौशल है। यह गाइड आपको ठीक उसी प्रक्रिया के माध्यम से ले जाने के लिए डिज़ाइन किया गया है। हम आपको अपना खुद का वेरिफ़ाएबल क्रेडेंशियल वेरिफ़ायर बनाने के लिए आवश्यक सब कुछ कवर करेंगे, मूल अवधारणाओं और मानकों से लेकर हस्ताक्षरों को मान्य करने और क्रेडेंशियल स्थिति की जाँच करने के चरण-दर-चरण कार्यान्वयन विवरण तक।
आगे बढ़ना चाहते हैं? आप इस ट्यूटोरियल के लिए पूर्ण, समाप्त परियोजना GitHub पर पा सकते हैं। इसे क्लोन करने और स्वयं आज़माने के लिए स्वतंत्र महसूस करें: https://github.com/corbado/digital-credentials-example
चलिए शुरू करते हैं।
शुरू करने से पहले, सुनिश्चित करें कि आपके पास है:
अब हम इनमें से प्रत्येक पूर्वापेक्षा को विस्तार से देखेंगे, जिसकी शुरुआत मानकों और प्रोटोकॉल से होगी जो इस mdoc-आधारित वेरिफ़ायर का आधार हैं।
हमारा वेरिफ़ायर निम्नलिखित के लिए बनाया गया है:
मानक / प्रोटोकॉल | विवरण |
---|---|
W3C VC | W3C वेरिफ़ाएबल क्रेडेंशियल डेटा मॉडल। यह डिजिटल क्रेडेंशियल के लिए मानक संरचना को परिभाषित करता है, जिसमें दावे, मेटाडेटा और सबूत शामिल हैं। |
SD-JWT | JWTs के लिए चयनात्मक प्रकटीकरण। JSON वेब टोकन पर आधारित VCs के लिए एक प्रारूप जो धारकों को एक क्रेडेंशियल से केवल विशिष्ट दावों को चुनिंदा रूप से प्रकट करने की अनुमति देता है, जिससे गोपनीयता बढ़ती है। |
ISO mDoc | ISO/IEC 18013-5। मोबाइल ड्राइविंग लाइसेंस (mDLs) और अन्य मोबाइल आईडी के लिए अंतर्राष्ट्रीय मानक, जो ऑफ़लाइन और ऑनलाइन उपयोग के लिए डेटा संरचनाओं और संचार प्रोटोकॉल को परिभाषित करता है। |
OpenID4VP | वेरिफ़ाएबल प्रेजेंटेशन के लिए OpenID। OAuth 2.0 पर बना एक इंटरऑपरेबल प्रेजेंटेशन प्रोटोकॉल। यह परिभाषित करता है कि एक वेरिफ़ायर क्रेडेंशियल का अनुरोध कैसे करता है और एक धारक का वॉलेट उन्हें कैसे प्रस्तुत करता है। |
इस ट्यूटोरियल के लिए, हम विशेष रूप से उपयोग करते हैं:
स्कोप पर ध्यान दें: जबकि हम व्यापक संदर्भ प्रदान करने के लिए संक्षेप में W3C VC और SD-JWT का परिचय देते हैं, यह ट्यूटोरियल विशेष रूप से OpenID4VP के माध्यम से ISO mDoc क्रेडेंशियल को लागू करता है। W3C-आधारित VCs इस उदाहरण के दायरे से बाहर हैं।
ISO/IEC 18013-5 mDoc मानक मोबाइल दस्तावेज़ों जैसे मोबाइल ड्राइविंग लाइसेंस (mDLs) के लिए संरचना और एन्कोडिंग को परिभाषित करता है। mDoc क्रेडेंशियल CBOR-एन्कोडेड, क्रिप्टोग्राफ़िक रूप से हस्ताक्षरित होते हैं, और सत्यापन के लिए डिजिटल रूप से प्रस्तुत किए जा सकते हैं। हमारा वेरिफ़ायर इन mdoc क्रेडेंशियल को डीकोड करने और मान्य करने पर ध्यान केंद्रित करेगा।
OpenID4VP डिजिटल क्रेडेंशियल का अनुरोध करने और प्रस्तुत करने के लिए एक इंटरऑपरेबल प्रोटोकॉल है, जो OAuth 2.0 और OpenID कनेक्ट के शीर्ष पर बनाया गया है। इस कार्यान्वयन में, OpenID4VP का उपयोग किया जाता है:
अब जब हमें मानकों और प्रोटोकॉल की स्पष्ट समझ है, तो हमें अपना वेरिफ़ायर बनाने के लिए सही टेक स्टैक चुनने की आवश्यकता है। हमारे विकल्प मजबूती, डेवलपर अनुभव और आधुनिक वेब पारिस्थितिकी तंत्र के साथ संगतता के लिए डिज़ाइन किए गए हैं।
हम अपने फ्रंटएंड और बैकएंड कोड दोनों के लिए TypeScript का उपयोग करेंगे। जावास्क्रिप्ट के एक सुपरसेट के रूप में, यह स्टैटिक टाइपिंग जोड़ता है, जो त्रुटियों को जल्दी पकड़ने में मदद करता है, कोड की गुणवत्ता में सुधार करता है, और जटिल अनुप्रयोगों को प्रबंधित करना आसान बनाता है। क्रेडेंशियल सत्यापन जैसे सुरक्षा-संवेदनशील संदर्भ में, टाइप सुरक्षा एक बहुत बड़ा लाभ है।
Next.js हमारी पसंद का फ्रेमवर्क है क्योंकि यह फुल-स्टैक एप्लिकेशन बनाने के लिए एक सहज, एकीकृत अनुभव प्रदान करता है।
redirect_uri
के रूप में कार्य
करने के लिए जिम्मेदार हैं।हमारा कार्यान्वयन फ्रंटएंड और बैकएंड के लिए पुस्तकालयों के एक विशिष्ट सेट पर निर्भर करता है:
openid-client
पर ध्यान दें: अधिक उन्नत, उत्पादन-ग्रेड वेरिफ़ायर सीधे बैकएंड पर
OpenID4VP प्रोटोकॉल को संभालने के लिए openid-client
लाइब्रेरी का उपयोग कर सकते हैं,
जिससे डायनामिक redirect_uri
जैसी सुविधाएँ सक्षम होती हैं। एक redirect_uri
के साथ
सर्वर-चालित OpenID4VP प्रवाह में, openid-client
का उपयोग सीधे vp_token
प्रतिक्रियाओं
को पार्स और मान्य करने के लिए किया जाएगा। इस ट्यूटोरियल के लिए, हम एक सरल,
ब्राउज़र-मध्यस्थता प्रवाह का उपयोग कर रहे हैं जिसके लिए इसकी आवश्यकता नहीं है, जिससे
प्रक्रिया को समझना आसान हो जाता है।
यह टेक स्टैक ब्राउज़र के डिजिटल क्रेडेंशियल API और ISO mDoc क्रेडेंशियल प्रारूप पर केंद्रित एक मजबूत, टाइप-सुरक्षित और स्केलेबल वेरिफ़ायर कार्यान्वयन सुनिश्चित करता है।
अपने वेरिफ़ायर का परीक्षण करने के लिए, आपको एक मोबाइल वॉलेट की आवश्यकता है जो ब्राउज़र के डिजिटल क्रेडेंशियल API के साथ इंटरैक्ट कर सके।
हम CMWallet का उपयोग करेंगे, जो Android के लिए एक मजबूत OpenID4VP-अनुपालन परीक्षण वॉलेट है।
CMWallet कैसे स्थापित करें (Android):
ध्यान दें: केवल उन स्रोतों से APK फ़ाइलें स्थापित करें जिन पर आप भरोसा करते हैं। प्रदान किया गया लिंक आधिकारिक परियोजना भंडार से है।
कार्यान्वयन में गोता लगाने से पहले, वेरिफ़ाएबल क्रेडेंशियल के आधारभूत क्रिप्टोग्राफिक अवधारणाओं को समझना आवश्यक है। यही उन्हें "सत्यापन योग्य" और भरोसेमंद बनाता है।
इसके मूल में, एक वेरिफ़ाएबल क्रेडेंशियल दावों का एक सेट है (जैसे नाम, जन्म तिथि, आदि) जिसे एक जारीकर्ता द्वारा डिजिटल रूप से हस्ताक्षरित किया गया है। एक डिजिटल हस्ताक्षर दो महत्वपूर्ण गारंटी प्रदान करता है:
डिजिटल हस्ताक्षर सार्वजनिक/निजी कुंजी क्रिप्टोग्राफी (जिसे असममित क्रिप्टोग्राफी भी कहा जाता है) का उपयोग करके बनाए जाते हैं। यहाँ यह हमारे संदर्भ में कैसे काम करता है:
DIDs पर ध्यान दें: इस ट्यूटोरियल में, हम DIDs के माध्यम से जारीकर्ता कुंजियों को हल नहीं करते हैं। उत्पादन में, जारीकर्ता आमतौर पर DIDs या अन्य आधिकारिक एंडपॉइंट के माध्यम से सार्वजनिक कुंजियों को उजागर करेंगे, जिनका उपयोग वेरिफ़ायर क्रिप्टोग्राफ़िक सत्यापन के लिए करेगा।
वेरिफ़ाएबल क्रेडेंशियल अक्सर JSON वेब टोकन (JWTs) के रूप में स्वरूपित होते हैं। एक JWT
दो पक्षों के बीच स्थानांतरित किए जाने वाले दावों का प्रतिनिधित्व करने का एक संक्षिप्त,
URL-सुरक्षित तरीका है। एक हस्ताक्षरित JWT (जिसे JWS भी कहा जाता है) के तीन भाग होते हैं जो
डॉट्स (.
) से अलग होते हैं:
alg
)।vc
दावा) के
वास्तविक दावे होते हैं, जिसमें issuer
, credentialSubject
, आदि शामिल हैं।// एक JWT संरचना का उदाहरण [हेडर].[पेलोड].[हस्ताक्षर]
ध्यान दें: JWT-आधारित वेरिफ़ाएबल क्रेडेंशियल इस ब्लॉग पोस्ट के दायरे से बाहर हैं। यह कार्यान्वयन ISO mDoc क्रेडेंशियल और OpenID4VP पर केंद्रित है, न कि W3C वेरिफ़ाएबल क्रेडेंशियल या JWT-आधारित क्रेडेंशियल पर।
एक वेरिफ़ायर के लिए यह जानना पर्याप्त नहीं है कि एक क्रेडेंशियल मान्य है; उसे यह भी जानना होगा कि क्रेडेंशियल प्रस्तुत करने वाला व्यक्ति वैध धारक है। यह किसी को चोरी किए गए क्रेडेंशियल का उपयोग करने से रोकता है।
यह एक वेरिफ़ाएबल प्रेजेंटेशन (VP) का उपयोग करके हल किया जाता है। एक VP एक या एक से अधिक VCs के चारों ओर एक रैपर है जिसे धारक द्वारा स्वयं हस्ताक्षरित किया जाता है।
प्रवाह इस प्रकार है:
हमारे वेरिफ़ायर को तब दो अलग-अलग हस्ताक्षर जाँच करनी चाहिए:
यह दो-स्तरीय जाँच क्रेडेंशियल की प्रामाणिकता और इसे प्रस्तुत करने वाले व्यक्ति की पहचान दोनों सुनिश्चित करती है, जिससे एक मजबूत और सुरक्षित विश्वास मॉडल बनता है।
ध्यान दें: W3C VC पारिस्थितिकी तंत्र में परिभाषित वेरिफ़ाएबल प्रेजेंटेशन की अवधारणा
इस ब्लॉग पोस्ट के दायरे से बाहर है। यहाँ
वेरिफ़ाएबल प्रेजेंटेशन शब्द OpenID4VP vp_token
प्रतिक्रिया को संदर्भित करता है, जो W3C VP के समान व्यवहार करता है लेकिन W3C के
JSON-LD हस्ताक्षर मॉडल के बजाय ISO mDoc सिमेंटिक्स पर आधारित है। यह
गाइड ISO mDoc क्रेडेंशियल और OpenID4VP पर केंद्रित है, न कि W3C वेरिफ़ाएबल प्रेजेंटेशन
या उनके हस्ताक्षर सत्यापन पर।
हमारी वेरिफ़ायर वास्तुकला हमारे वेब एप्लिकेशन को उपयोगकर्ता के मोबाइल CMWallet से जोड़ने के लिए एक सुरक्षित मध्यस्थ के रूप में ब्राउज़र के अंतर्निहित डिजिटल क्रेडेंशियल API का उपयोग करती है। यह दृष्टिकोण ब्राउज़र को नेटिव QR कोड प्रदर्शन और वॉलेट संचार को संभालने देकर प्रवाह को सरल बनाता है।
navigator.credentials.get()
API को पास करना है, परिणाम प्राप्त करना है, और इसे सत्यापन
के लिए हमारे बैकएंड को अग्रेषित करना है।openid4vp
प्रोटोकॉल को समझता है, और मूल रूप से एक QR कोड उत्पन्न करता है। यह
तब वॉलेट से प्रतिक्रिया लौटने की प्रतीक्षा करता है।यहाँ एक अनुक्रम आरेख है जो पूर्ण और सटीक प्रवाह को दर्शाता है:
प्रवाह समझाया गया:
/api/verify/start
) को कॉल करता है, जो
क्वेरी और एक नॉनस युक्त एक अनुरोध ऑब्जेक्ट उत्पन्न करता है, फिर उसे लौटाता है।navigator.credentials.get()
को
कॉल करता है।openid4vp
प्रोटोकॉल अनुरोध को देखता है और मूल रूप से
एक QR कोड प्रदर्शित करता है। .get()
वादा अब लंबित है।ध्यान दें: यह QR कोड प्रवाह डेस्कटॉप ब्राउज़र पर होता है। मोबाइल ब्राउज़र (प्रायोगिक
ध्वज सक्षम के साथ Android Chrome) पर, ब्राउज़र सीधे उसी डिवाइस पर संगत
वॉलेट के साथ संवाद कर सकता है, जिससे QR कोड
स्कैनिंग की आवश्यकता समाप्त हो जाती है। Android Chrome पर इस सुविधा को सक्षम करने के
लिए, chrome://flags#web-identity-digital-credentials
पर जाएँ और ध्वज को "सक्षम" पर सेट
करें।
.get()
वादा
अंततः हल हो जाता है, प्रेजेंटेशन पेलोड वितरित करता है।/api/verify/finish
एंडपॉइंट पर
प्रेजेंटेशन पेलोड को POST करता है। बैकएंड नॉनस और क्रेडेंशियल को मान्य करता है।अब जब हमें मानकों, प्रोटोकॉल और वास्तुशिल्प प्रवाह की ठोस समझ है, तो हम अपना वेरिफ़ायर बनाना शुरू कर सकते हैं।
साथ चलें या अंतिम कोड का उपयोग करें
अब हम सेटअप और कोड कार्यान्वयन के माध्यम से चरण-दर-चरण चलेंगे। यदि आप सीधे तैयार उत्पाद पर जाना पसंद करते हैं, तो आप हमारे GitHub रिपॉजिटरी से पूरी परियोजना को क्लोन कर सकते हैं और इसे स्थानीय रूप से चला सकते हैं।
git clone https://github.com/corbado/digital-credentials-example.git
सबसे पहले, हम एक नया Next.js प्रोजेक्ट शुरू करेंगे, आवश्यक निर्भरताएँ स्थापित करेंगे, और अपना डेटाबेस शुरू करेंगे।
अपना टर्मिनल खोलें, उस डायरेक्टरी में जाएँ जहाँ आप अपना प्रोजेक्ट बनाना चाहते हैं, और निम्न कमांड चलाएँ। हम इस प्रोजेक्ट के लिए ऐप राउटर, TypeScript और Tailwind CSS का उपयोग कर रहे हैं।
npx create-next-app@latest . --ts --eslint --tailwind --app --src-dir --import-alias "@/*" --use-npm
यह कमांड आपकी वर्तमान डायरेक्टरी में एक नया Next.js एप्लिकेशन बनाता है।
अगला, हमें उन पुस्तकालयों को स्थापित करने की आवश्यकता है जो CBOR डीकोडिंग, डेटाबेस कनेक्शन और UUID पीढ़ी को संभालेंगे।
npm install cbor-web mysql2 uuid @types/uuid
यह कमांड स्थापित करता है:
cbor-web
: mdoc क्रेडेंशियल पेलोड को डीकोड करने के लिए।mysql2
: हमारे डेटाबेस के लिए MySQL क्लाइंट।uuid
: अद्वितीय चुनौती स्ट्रिंग उत्पन्न करने के लिए।@types/uuid
: uuid
लाइब्रेरी के लिए TypeScript प्रकार।हमारे बैकएंड को OIDC सत्र डेटा संग्रहीत करने के लिए एक MySQL डेटाबेस की आवश्यकता होती है,
यह सुनिश्चित करते हुए कि प्रत्येक सत्यापन प्रवाह सुरक्षित और स्टेटफुल है। हमने इसे आसान
बनाने के लिए एक docker-compose.yml
फ़ाइल शामिल की है।
यदि आपने रिपॉजिटरी को क्लोन किया है, तो आप बस docker-compose up -d
चला सकते हैं। यदि आप
खरोंच से निर्माण कर रहे हैं, तो निम्न सामग्री के साथ docker-compose.yml
नामक एक फ़ाइल
बनाएँ:
services: mysql: image: mysql:8.0 restart: always environment: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_DATABASE: digital_credentials MYSQL_USER: app_user MYSQL_PASSWORD: app_password ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql - ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] timeout: 20s retries: 10 volumes: mysql_data:
इस Docker Compose सेटअप के लिए एक SQL आरंभीकरण स्क्रिप्ट की भी आवश्यकता होती है। sql
नामक एक डायरेक्टरी बनाएँ और उसके अंदर, आवश्यक तालिकाओं को सेट करने के लिए निम्न सामग्री के
साथ init.sql
नामक एक फ़ाइल बनाएँ:
-- Create database if not exists CREATE DATABASE IF NOT EXISTS digital_credentials; USE digital_credentials; -- Table for storing challenges CREATE TABLE IF NOT EXISTS challenges ( id VARCHAR(36) PRIMARY KEY, challenge VARCHAR(255) NOT NULL UNIQUE, expires_at TIMESTAMP NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, used BOOLEAN DEFAULT FALSE, INDEX idx_challenge (challenge), INDEX idx_expires_at (expires_at) ); -- Table for storing verification sessions CREATE TABLE IF NOT EXISTS verification_sessions ( id VARCHAR(36) PRIMARY KEY, challenge_id VARCHAR(36), status ENUM('pending', 'verified', 'failed', 'expired') DEFAULT 'pending', presentation_data JSON, verified_at TIMESTAMP NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (challenge_id) REFERENCES challenges(id) ON DELETE CASCADE, INDEX idx_challenge_id (challenge_id), INDEX idx_status (status) ); -- Table for storing verified credentials data (optional) CREATE TABLE IF NOT EXISTS verified_credentials ( id VARCHAR(36) PRIMARY KEY, session_id VARCHAR(36), credential_type VARCHAR(255), issuer VARCHAR(255), subject VARCHAR(255), claims JSON, verified_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (session_id) REFERENCES verification_sessions(id) ON DELETE CASCADE, INDEX idx_session_id (session_id), INDEX idx_credential_type (credential_type) );
दोनों फाइलें बन जाने के बाद, अपने टर्मिनल को प्रोजेक्ट रूट में खोलें और चलाएँ:
docker-compose up -d
यह कमांड बैकग्राउंड में एक MySQL कंटेनर शुरू करेगा।
हमारा Next.js एप्लिकेशन फ्रंटएंड और बैकएंड के बीच चिंताओं को अलग करने के लिए संरचित है, भले ही वे एक ही प्रोजेक्ट का हिस्सा हों।
src/app/page.tsx
): एक एकल React पृष्ठ जो सत्यापन
प्रवाह शुरू करता है और परिणाम प्रदर्शित करता है। यह ब्राउज़र के डिजिटल क्रेडेंशियल API
के साथ इंटरैक्ट करता है।src/app/api/verify/...
):
start/route.ts
: OpenID4VP अनुरोध और एक सुरक्षा नॉनस उत्पन्न करता है।finish/route.ts
: वॉलेट से प्रस्तुति प्राप्त करता है (ब्राउज़र के माध्यम से), नॉनस
को मान्य करता है, और क्रेडेंशियल को डीकोड करता है।src/lib/
):
database.ts
: सभी डेटाबेस इंटरैक्शन का प्रबंधन करता है (चुनौतियाँ बनाना, सत्रों का
सत्यापन करना)।crypto.ts
: CBOR-आधारित mDoc क्रेडेंशियल की डीकोडिंग को संभालता है।यहाँ आंतरिक वास्तुकला को दर्शाने वाला एक चित्र है:
हमारा फ्रंटएंड जानबूझकर हल्का बनाया गया है। इसकी प्राथमिक जिम्मेदारी सत्यापन प्रवाह के लिए उपयोगकर्ता-सामना करने वाले ट्रिगर के रूप में कार्य करना और हमारे बैकएंड और ब्राउज़र की नेटिव क्रेडेंशियल हैंडलिंग क्षमताओं दोनों के साथ संवाद करना है। इसमें कोई जटिल प्रोटोकॉल तर्क नहीं है; वह सब प्रत्यायोजित है।
विशेष रूप से, फ्रंटएंड निम्नलिखित को संभालेगा:
/api/verify/start
को कॉल करता है और एक संरचित JSON
पेलोड (protocol
, request
, state
) प्राप्त करता है जो बताता है कि वॉलेट को वास्तव
में क्या प्रस्तुत करना चाहिए।navigator.credentials.get()
को सौंपता
है, जो एक नेटिव QR कोड प्रस्तुत करता है और वॉलेट प्रतिक्रिया की प्रतीक्षा करता है।/api/verify/finish
एंडपॉइंट पर एक POST अनुरोध में भेजता है।मुख्य तर्क startVerification
फ़ंक्शन में है:
// src/app/page.tsx const startVerification = async () => { setLoading(true); setVerificationResult(null); try { // 1. जाँच करें कि क्या ब्राउज़र API का समर्थन करता है if (!navigator.credentials?.get) { throw new Error("ब्राउज़र क्रेडेंशियल API का समर्थन नहीं करता है।"); } // 2. हमारे बैकएंड से एक अनुरोध ऑब्जेक्ट के लिए पूछें const res = await fetch("/api/verify/start"); const { protocol, request } = await res.json(); // 3. उस ऑब्जेक्ट को ब्राउज़र को सौंपें - यह नेटिव QR कोड को ट्रिगर करता है const credential = await (navigator.credentials as any).get({ mediation: "required", digital: { requests: [ { protocol, // "openid4vp" data: request, // इसमें dcql_query, nonce, आदि शामिल हैं। }, ], }, }); // 4. सर्वर-साइड जाँच के लिए हमारे फिनिश एंडपॉइंट पर वॉलेट प्रतिक्रिया (ब्राउज़र से) अग्रेषित करें const verifyRes = await fetch("/api/verify/finish", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(credential), }); const result = await verifyRes.json(); if (verifyRes.ok && result.verified) { setVerificationResult(`सफलता: ${result.message}`); } else { throw new Error(result.message || "सत्यापन विफल।"); } } catch (err) { setVerificationResult(`त्रुटि: ${(err as Error).message}`); } finally { setLoading(false); } };
यह फ़ंक्शन फ्रंटएंड तर्क के चार प्रमुख चरणों को दिखाता है: API समर्थन की जाँच करना, बैकएंड से अनुरोध प्राप्त करना, ब्राउज़र API को कॉल करना, और सत्यापन के लिए परिणाम वापस भेजना। फ़ाइल का बाकी हिस्सा स्थिति और UI रेंडरिंग के लिए मानक React बॉयलरप्लेट है, जिसे आप GitHub रिपॉजिटरी में देख सकते हैं।
digital
और mediation: 'required'
क्यों?#आप देख सकते हैं कि navigator.credentials.get()
पर हमारी कॉल सरल उदाहरणों से अलग दिखती
है। ऐसा इसलिए है क्योंकि हम आधिकारिक
W3C डिजिटल क्रेडेंशियल API विनिर्देश
का सख्ती से पालन कर रहे हैं।
digital
सदस्य: विनिर्देश की आवश्यकता है कि सभी डिजिटल क्रेडेंशियल अनुरोध एक
digital
ऑब्जेक्ट के अंदर नेस्टेड हों। यह इस API के लिए एक स्पष्ट, मानकीकृत नेमस्पेस
प्रदान करता है, इसे अन्य क्रेडेंशियल प्रकारों (जैसे password
या federated
) से अलग
करता है और भविष्य में बिना किसी टकराव के विस्तार की अनुमति देता है।
mediation: 'required'
: यह विकल्प एक महत्वपूर्ण सुरक्षा और उपयोगकर्ता-अनुभव सुविधा
है। यह लागू करता है कि उपयोगकर्ता को क्रेडेंशियल अनुरोध को स्वीकृत करने के लिए एक
प्रॉम्प्ट (जैसे, एक बायोमेट्रिक स्कैन, पिन प्रविष्टि, या एक सहमति स्क्रीन) के साथ सक्रिय
रूप से बातचीत करनी चाहिए। इसके बिना, एक वेबसाइट संभावित रूप से पृष्ठभूमि में चुपचाप
क्रेडेंशियल तक पहुँचने का प्रयास कर सकती है, जो एक महत्वपूर्ण गोपनीयता जोखिम पैदा करता
है। मध्यस्थता की आवश्यकता से, हम यह सुनिश्चित करते हैं कि उपयोगकर्ता हमेशा नियंत्रण में
रहे और प्रत्येक लेनदेन के लिए स्पष्ट सहमति दे।
React UI के साथ अब हमें दो API रूटों की आवश्यकता है जो सर्वर पर भारी-भरकम काम करते हैं:
/api/verify/start
– एक OpenID4VP अनुरोध बनाता है, MySQL में एक बार की चुनौती को
बनाए रखता है और सब कुछ ब्राउज़र को वापस सौंपता है।/api/verify/finish
– वॉलेट प्रतिक्रिया प्राप्त करता है, चुनौती को मान्य करता है,
क्रेडेंशियल को सत्यापित और डीकोड करता है, और अंत में UI को एक संक्षिप्त JSON परिणाम
लौटाता है।/api/verify/start
: OpenID4VP अनुरोध उत्पन्न करें#// src/app/api/verify/start/route.ts import { NextResponse } from "next/server"; import { v4 as uuidv4 } from "uuid"; import { createChallenge, cleanupExpiredChallenges } from "@/lib/database"; export async function GET() { // 1️⃣ एक अल्पकालिक, यादृच्छिक नॉनस (चुनौती) बनाएँ const challenge = uuidv4(); const challengeId = uuidv4(); const expiresAt = new Date(Date.now() + 5 * 60 * 1000); await createChallenge(challengeId, challenge, expiresAt); cleanupExpiredChallenges().catch(console.error); // 2️⃣ एक DCQL क्वेरी बनाएँ जो बताती है कि हमें *क्या* चाहिए const dcqlQuery = { credentials: [ { id: "cred1", format: "mso_mdoc", meta: { doctype_value: "eu.europa.ec.eudi.pid.1" }, claims: [ { path: ["eu.europa.ec.eudi.pid.1", "family_name"] }, { path: ["eu.europa.ec.eudi.pid.1", "given_name"] }, { path: ["eu.europa.ec.eudi.pid.1", "birth_date"] }, ], }, ], }; // 3️⃣ एक ऑब्जेक्ट लौटाएँ जिसे ब्राउज़र navigator.credentials.get() को पास कर सकता है return NextResponse.json({ protocol: "openid4vp", // ब्राउज़र को बताता है कि कौन सा वॉलेट प्रोटोकॉल उपयोग करना है request: { dcql_query: dcqlQuery, // क्या प्रस्तुत करना है nonce: challenge, // रीप्ले-विरोधी response_type: "vp_token", response_mode: "dc_api", // वॉलेट सीधे /finish पर पोस्ट करेगा }, state: { credential_type: "mso_mdoc", // बाद की जाँच के लिए रखा गया nonce: challenge, challenge_id: challengeId, }, }); }
मुख्य पैरामीटर
• nonce
– क्रिप्टोग्राफ़िक चुनौती जो अनुरोध
और प्रतिक्रिया को बांधती है (रीप्ले को रोकती है)। • dcql_query
– एक ऑब्जेक्ट जो
हमें आवश्यक सटीक दावों का वर्णन करता है। इस गाइड के लिए, हम डिजिटल क्रेडेंशियल क्वेरी
भाषा के हालिया ड्राफ्ट से प्रेरित एक dcql_query
संरचना का उपयोग करते हैं, भले ही यह
अभी तक एक अंतिम मानक नहीं है। • state
– वॉलेट द्वारा वापस प्रतिध्वनित मनमाना JSON
ताकि हम DB रिकॉर्ड देख सकें।
फ़ाइल src/lib/database.ts
चुनौतियों और सत्यापन सत्रों (सम्मिलित करें, पढ़ें, उपयोग के
रूप में चिह्नित करें) के लिए बुनियादी MySQL संचालन को लपेटती है। इस तर्क को एक ही मॉड्यूल
में रखने से बाद में डेटास्टोर को बदलना आसान हो जाता है।
/api/verify/finish
: प्रेजेंटेशन को मान्य और डीकोड करें#// src/app/api/verify/finish/route.ts import { NextResponse, NextRequest } from "next/server"; import { v4 as uuidv4 } from "uuid"; import { getChallenge, markChallengeAsUsed, createVerificationSession, updateVerificationSession, } from "@/lib/database"; import { decodeDigitalCredential, decodeAllNamespaces } from "@/lib/crypto"; export async function POST(request: NextRequest) { const body = await request.json(); // 1️⃣ वेरिफ़ाएबल प्रेजेंटेशन के टुकड़ों को निकालें const vpTokenMap = body.vp_token ?? body.data?.vp_token; const state = body.state; const mdocToken = vpTokenMap?.cred1; // हमने dcqlQuery में इस ID के लिए कहा था if (!vpTokenMap || !state || !mdocToken) { return NextResponse.json( { verified: false, message: "विकृत प्रतिक्रिया" }, { status: 400 }, ); } // 2️⃣ एक-बार-उपयोग चुनौती सत्यापन const stored = await getChallenge(state.nonce); if (!stored) { return NextResponse.json( { verified: false, message: "अमान्य या समाप्त चुनौती" }, { status: 400 }, ); } const sessionId = uuidv4(); await createVerificationSession(sessionId, stored.id); // 3️⃣ (छद्म) क्रिप्टोग्राफ़िक जाँच - उत्पादन में वास्तविक mDL सत्यापन के साथ बदलें // एक वास्तविक एप्लिकेशन में, आप जारीकर्ता की सार्वजनिक कुंजी के विरुद्ध mdoc हस्ताक्षर का पूर्ण // क्रिप्टोग्राफ़िक सत्यापन करने के लिए एक समर्पित लाइब्रेरी का उपयोग करेंगे। const isValid = mdocToken.length > 0; if (!isValid) { await updateVerificationSession(sessionId, "failed", { reason: "mdoc सत्यापन विफल", }); return NextResponse.json( { verified: false, message: "क्रेडेंशियल सत्यापन विफल" }, { status: 400 }, ); } // 4️⃣ मोबाइल-डीएल (mdoc) पेलोड को मानव पठनीय JSON में डीकोड करें const decoded = await decodeDigitalCredential(mdocToken); const readable = decodeAllNamespaces(decoded)["eu.europa.ec.eudi.pid.1"]; await markChallengeAsUsed(state.nonce); await updateVerificationSession(sessionId, "verified", { readable }); return NextResponse.json({ verified: true, message: "mdoc क्रेडेंशियल सफलतापूर्वक सत्यापित किया गया!", credentialData: readable, sessionId, }); }
वॉलेट प्रतिक्रिया में महत्वपूर्ण फ़ील्ड
• vp_token
– मैप जो वॉलेट द्वारा लौटाए गए प्रत्येक क्रेडेंशियल को रखता है। हमारे
डेमो के लिए हम vp_token.cred1
खींचते हैं। • state
– /start
में हमारे द्वारा
प्रदान किए गए ब्लॉब की प्रतिध्वनि; इसमें nonce
होता है ताकि हम DB रिकॉर्ड देख सकें। •
mdocToken
– एक Base64URL-एन्कोडेड CBOR संरचना जो ISO mDoc का प्रतिनिधित्व करती है।
जब वेरिफ़ायर ब्राउज़र से एक mdoc क्रेडेंशियल प्राप्त करता है, तो यह एक Base64URL स्ट्रिंग
होती है जिसमें CBOR-एन्कोडेड बाइनरी डेटा होता है। वास्तविक दावों को निकालने के लिए,
finish
एंडपॉइंट src/lib/crypto.ts
से हेल्पर फ़ंक्शंस का उपयोग करके एक बहु-चरणीय
डीकोडिंग प्रक्रिया करता है।
decodeDigitalCredential
फ़ंक्शन एन्कोडेड स्ट्रिंग से एक प्रयोग करने योग्य ऑब्जेक्ट में
रूपांतरण को संभालता है:
// src/lib/crypto.ts export async function decodeDigitalCredential(encodedCredential: string) { // 1. Base64URL को मानक Base64 में बदलें const base64UrlToBase64 = (input: string) => { let base64 = input.replace(/-/g, "+").replace(/_/g, "/"); const pad = base64.length % 4; if (pad) base64 += "=".repeat(4 - pad); return base64; }; const base64 = base64UrlToBase64(encodedCredential); // 2. Base64 को बाइनरी में डीकोड करें const binaryString = atob(base64); const byteArray = Uint8Array.from(binaryString, (char) => char.charCodeAt(0)); // 3. CBOR को डीकोड करें const decoded = await cbor.decodeFirst(byteArray); return decoded; }
cbor-web
लाइब्रेरी का उपयोग करता है।decodeAllNamespaces
फ़ंक्शन प्रासंगिक नेमस्पेस से वास्तविक दावों को निकालने के लिए डीकोड
किए गए CBOR ऑब्जेक्ट को और संसाधित करता है:
// src/lib/crypto.ts export function decodeAllNamespaces(jsonObj) { const decoded = {}; try { jsonObj.documents.forEach((doc, idx) => { // 1) issuerSigned.nameSpaces: const issuerNS = doc.issuerSigned?.nameSpaces || {}; Object.entries(issuerNS).forEach(([nsName, entries]) => { if (!decoded[nsName]) decoded[nsName] = {}; (entries as any[]).forEach((entry) => { const bytes = Uint8Array.from(entry.value); const decodedEntry = cbor.decodeFirstSync(bytes); Object.assign(decoded[nsName], decodedEntry); }); }); // 2) deviceSigned.nameSpaces (यदि मौजूद हो): const deviceNS = doc.deviceSigned?.nameSpaces; if (deviceNS?.value?.data) { const bytes = Uint8Array.from(deviceNS.value); decoded[`deviceSigned_ns_${idx}`] = cbor.decodeFirstSync(bytes); } }); } catch (e) { console.error(e); } return decoded; }
eu.europa.ec.eudi.pid.1
) वास्तविक दावा
मानों (जैसे नाम, जन्म तिथि, आदि) को निकालने के लिए।इन चरणों से गुजरने के बाद, फिनिश एंडपॉइंट को mdoc से दावों वाला एक मानव-पठनीय ऑब्जेक्ट प्राप्त होता है, उदाहरण के लिए:
{ "family_name": "Doe", "given_name": "John", "birth_date": "1990-01-01" }
यह प्रक्रिया सुनिश्चित करती है कि वेरिफ़ायर प्रदर्शन और आगे की प्रक्रिया के लिए mdoc क्रेडेंशियल से आवश्यक जानकारी को सुरक्षित और मज़बूती से निकाल सकता है।
फिनिश एंडपॉइंट फ्रंटएंड को एक न्यूनतम JSON ऑब्जेक्ट लौटाता है:
{ "verified": true, "message": "mdoc क्रेडेंशियल सफलतापूर्वक सत्यापित किया गया!", "credentialData": { "family_name": "Doe", "given_name": "John", "birth_date": "1990-01-01" } }
फ्रंटएंड इस प्रतिक्रिया को startVerification()
में प्राप्त करता है और बस इसे React
स्थिति में बनाए रखता है ताकि हम एक अच्छा पुष्टिकरण कार्ड प्रस्तुत कर सकें या व्यक्तिगत
दावों को प्रदर्शित कर सकें - जैसे “आपका स्वागत है, जॉन डो (जन्म 1990-01-01)!”।
अब आपके पास एक पूर्ण, काम करने वाला वेरिफ़ायर है जो ब्राउज़र की नेटिव क्रेडेंशियल हैंडलिंग क्षमताओं का उपयोग करता है। यहाँ इसे स्थानीय रूप से कैसे चलाना है और इसे एक प्रूफ-ऑफ-कॉन्सेप्ट से उत्पादन-तैयार एप्लिकेशन में ले जाने के लिए आप क्या कर सकते हैं।
रिपॉजिटरी को क्लोन करें:
git clone https://github.com/corbado/digital-credentials-example.git cd digital-credentials-example
निर्भरताएँ स्थापित करें:
npm install
डेटाबेस शुरू करें: सुनिश्चित करें कि आपके मशीन पर Docker चल रहा है, फिर MySQL कंटेनर शुरू करें:
docker-compose up -d
एप्लिकेशन चलाएँ:
npm run dev
अपने ब्राउज़र को http://localhost:3000
पर खोलें, और आपको वेरिफ़ायर का UI देखना
चाहिए। अब आप QR कोड को स्कैन करने और सत्यापन प्रवाह को पूरा करने के लिए अपने CMWallet
का उपयोग कर सकते हैं।
यह ट्यूटोरियल एक वेरिफ़ायर के लिए मूलभूत बिल्डिंग ब्लॉक प्रदान करता है। इसे उत्पादन-तैयार बनाने के लिए, आपको कई अतिरिक्त सुविधाएँ लागू करने की आवश्यकता होगी:
पूर्ण क्रिप्टोग्राफ़िक सत्यापन: वर्तमान कार्यान्वयन एक प्लेसहोल्डर जाँच
(mdocToken.length > 0
) का उपयोग करता है। एक वास्तविक दुनिया के परिदृश्य में, आपको
जारीकर्ता की सार्वजनिक कुंजी के विरुद्ध mdoc हस्ताक्षर का पूर्ण
क्रिप्टोग्राफ़िक सत्यापन करना होगा (जैसे, उनके DID को हल करके या उनके सार्वजनिक कुंजी
प्रमाणपत्र को प्राप्त करके)। DID समाधान मानकों के लिए,
W3C DID समाधान विनिर्देश का संदर्भ लें।
जारीकर्ता निरस्तीकरण जाँच: क्रेडेंशियल को उनकी समाप्ति तिथि से पहले जारीकर्ता द्वारा रद्द किया जा सकता है। एक उत्पादन वेरिफ़ायर को जारीकर्ता द्वारा प्रदान की गई एक निरस्तीकरण सूची या स्थिति एंडपॉइंट से पूछकर क्रेडेंशियल की स्थिति की जाँच करनी चाहिए। W3C वेरिफ़ाएबल क्रेडेंशियल स्थिति सूची क्रेडेंशियल निरस्तीकरण सूचियों के लिए मानक प्रदान करती है।
मजबूत त्रुटि हैंडलिंग और सुरक्षा: व्यापक त्रुटि हैंडलिंग, इनपुट सत्यापन, API एंडपॉइंट्स पर दर-सीमन जोड़ें, और सुनिश्चित करें कि सभी संचार HTTPS (TLS) पर हों ताकि पारगमन में डेटा की सुरक्षा हो सके। OWASP API सुरक्षा दिशानिर्देश व्यापक API सुरक्षा सर्वोत्तम प्रथाओं को प्रदान करते हैं।
एकाधिक क्रेडेंशियल प्रकारों के लिए समर्थन: यदि आप केवल यूरोपीय
डिजिटल पहचान (EUDI) PID क्रेडेंशियल से अधिक प्राप्त करने
की उम्मीद करते हैं, तो विभिन्न doctype
मानों और क्रेडेंशियल प्रारूपों को संभालने के
लिए तर्क का विस्तार करें।
W3C वेरिफ़ाएबल क्रेडेंशियल डेटा मॉडल व्यापक VC
प्रारूप विनिर्देश प्रदान करता है।
यह उदाहरण जानबूझकर कोर ब्राउज़र-मध्यस्थता प्रवाह पर केंद्रित है ताकि इसे समझना आसान हो सके। निम्नलिखित विषय दायरे से बाहर माने जाते हैं:
redirect_uri
या डायनामिक क्लाइंट पंजीकरण का उपयोग करके
सीधे वॉलेट-टू-बैकएंड संचार जैसी अधिक जटिल OpenID4VP सुविधाओं को लागू नहीं करते हैं।इस नींव पर निर्माण करके और इन अगले चरणों को शामिल करके, आप एक मजबूत और सुरक्षित वेरिफ़ायर विकसित कर सकते हैं जो आपके अपने अनुप्रयोगों में डिजिटल क्रेडेंशियल पर भरोसा करने और उन्हें मान्य करने में सक्षम है।
बस इतना ही! 250 से कम TypeScript लाइनों के साथ, अब हमारे पास एक एंड-टू-एंड वेरिफ़ायर है जो:
उत्पादन में, आप प्लेसहोल्डर सत्यापन को पूर्ण ISO 18013-5 जाँचों से बदल देंगे, जारीकर्ता निरस्तीकरण लुक-अप, दर-सीमन, ऑडिट लॉगिंग, और निश्चित रूप से, एंड-टू-एंड TLS जोड़ेंगे—लेकिन कोर बिल्डिंग ब्लॉक बिल्कुल वही रहते हैं।
यहाँ कुछ प्रमुख संसाधन, विनिर्देश और उपकरण हैं जिनका इस ट्यूटोरियल में उपयोग या संदर्भ दिया गया है:
प्रोजेक्ट रिपॉजिटरी:
प्रमुख विनिर्देश:
उपकरण:
लाइब्रेरी:
Related Articles
Table of Contents