REST API टोकन-आधारित प्रमाणीकरण


122

मैं एक REST API विकसित कर रहा हूं, जिसे प्रमाणीकरण की आवश्यकता है। क्योंकि प्रमाणीकरण स्वयं HTTP पर एक बाहरी वेब सेवा के माध्यम से होता है, इसलिए मैंने तर्क दिया कि हम प्रमाणीकरण सेवा को बार-बार कॉल करने से बचने के लिए टोकन भेजेंगे। जो मुझे मेरे पहले सवाल पर बड़े करीने से लाता है:

क्या यह वास्तव में केवल क्लाइंट के लिए प्रत्येक अनुरोध पर HTTP बेसिक ऑथेंटिकेशन का उपयोग करने और प्रमाणीकरण सेवा सर्वर-साइड पर कॉल करने से बेहतर है?

बेसिक ऑथ सॉल्यूशन का फ़ायदा है कि कंटेंट के लिए रिक्वेस्ट शुरू होने से पहले सर्वर को फुल राउंड-ट्रिप की ज़रूरत नहीं है। टोकन संभावित रूप से अधिक लचीले हो सकते हैं (यानी केवल विशेष संसाधनों या कार्यों के लिए अधिकार प्रदान करते हैं), लेकिन यह मेरे सरल उपयोग मामले की तुलना में OAuth संदर्भ के लिए अधिक उपयुक्त लगता है।

वर्तमान में टोकन इस तरह हासिल किए जाते हैं:

curl -X POST localhost/token --data "api_key=81169d80...
                                     &verifier=2f5ae51a...
                                     &timestamp=1234567
                                     &user=foo
                                     &pass=bar"

api_key, timestampऔर verifierसभी अनुरोधों के लिए आवश्यक हैं। "सत्यापनकर्ता" द्वारा लौटाया जाता है:

sha1(timestamp + api_key + shared_secret)

मेरा इरादा केवल ज्ञात पार्टियों से कॉल की अनुमति देना है, और कॉल को पुन: उपयोग करने से रोकने के लिए है।

क्या यह काफी अच्छा है? Underkill? Overkill?

हाथ में एक टोकन के साथ, ग्राहक संसाधनों का अधिग्रहण कर सकते हैं:

curl localhost/posts?api_key=81169d80...
                    &verifier=81169d80...
                    &token=9fUyas64...
                    &timestamp=1234567

सबसे सरल कॉल संभव के लिए, यह एक प्रकार की भयावह क्रिया है। यह देखते हुए कि shared_secret(न्यूनतम) एक iOS एप्लिकेशन में विंड को एम्बेड किया जा रहा है, जिससे मुझे लगता है कि इसे निकाला जा सकता है, क्या यह सुरक्षा की झूठी भावना से परे कुछ भी पेश कर रहा है?


2
Sha1 (टाइमस्टैम्प + एपि_क + शर्ड_सेक्रेट) का उपयोग करने के बजाय आपको एक बेहतर सुरक्षा हैशिंग en.wikipedia.org/wiki/Hash-based_message_authentication_code
Miguel A. Carrasco

@ MiguelA.Carrasco और 2017 में सर्वसम्मति से लगता है कि bCrypt नया हैशिंग टूल है।
शॉन

जवाबों:


94

मुझे सब कुछ अलग करने और अलगाव में प्रत्येक समस्या का समाधान करने दें:

प्रमाणीकरण

प्रमाणीकरण के लिए, बैसियोथ का यह लाभ है कि यह प्रोटोकॉल स्तर पर एक परिपक्व समाधान है। इसका मतलब है कि "बाद में फसल हो सकती है" बहुत सारी समस्याएं आपके लिए पहले से ही हल हैं। उदाहरण के लिए, बेसअथ के साथ, उपयोगकर्ता एजेंटों को पता है कि पासवर्ड एक पासवर्ड है, इसलिए वे इसे कैश नहीं करते हैं।

प्रामाणिक सर्वर लोड

यदि आप अपने सर्वर पर प्रमाणीकरण को कैशिंग करने के बजाय उपयोगकर्ता को टोकन भेजते हैं, तो आप अभी भी वही काम कर रहे हैं: प्रमाणीकरण जानकारी कैशिंग। अंतर केवल इतना है कि आप उपयोगकर्ता को कैशिंग की जिम्मेदारी दे रहे हैं। यह बिना किसी लाभ के उपयोगकर्ता के लिए अनावश्यक श्रम की तरह लगता है, इसलिए मैं सुझाव देता हूं कि आप अपने सर्वर पर पारदर्शी रूप से इसे संभालें।

ट्रांसमिशन सुरक्षा

यदि एसएसएल कनेक्शन का उपयोग कर सकते हैं, तो बस इतना ही है, कनेक्शन सुरक्षित है *। आकस्मिक एकाधिक निष्पादन को रोकने के लिए, आप कई यूआरएल फ़िल्टर कर सकते हैं या उपयोगकर्ताओं को URL में एक यादृच्छिक घटक ("नॉन") शामिल करने के लिए कह सकते हैं।

url = username:key@myhost.com/api/call/nonce

यदि यह संभव नहीं है, और प्रेषित जानकारी गुप्त नहीं है, तो मैं एक हैश के साथ अनुरोध को सुरक्षित करने की सलाह देता हूं, जैसा कि आपने टोकन दृष्टिकोण में सुझाव दिया था। चूँकि हैश सुरक्षा प्रदान करता है, आप अपने उपयोगकर्ताओं को निर्देश दे सकते हैं कि हैश को आधारशिला पासवर्ड प्रदान करें। बेहतर मजबूती के लिए, मैं पुनरावृत्ति के हमलों को रोकने के लिए "नॉन" के रूप में टाइमस्टैम्प के बजाय एक यादृच्छिक स्ट्रिंग का उपयोग करने की सलाह देता हूं (दो कानूनी अनुरोध उसी सेकंड के दौरान किए जा सकते हैं)। अलग "साझा रहस्य" और "एपीआई कुंजी" फ़ील्ड प्रदान करने के बजाय, आप बस एपी कुंजी को साझा रहस्य के रूप में उपयोग कर सकते हैं, और फिर एक नमक का उपयोग करें जो इंद्रधनुष तालिका हमलों को रोकने के लिए नहीं बदलता है। उपयोगकर्ता नाम फ़ील्ड नॉन को भी डालने के लिए एक अच्छी जगह की तरह लगती है, क्योंकि यह ऑर्टिकल का हिस्सा है। तो अब आपके पास इस तरह से एक साफ कॉल है:

nonce = generate_secure_password(length: 16);
one_time_key = nonce + '-' + sha1(nonce+salt+shared_key);
url = username:one_time_key@myhost.com/api/call

यह सच है कि यह थोड़ा श्रमसाध्य है। ऐसा इसलिए है क्योंकि आप प्रोटोकॉल स्तर के समाधान (जैसे एसएसएल) का उपयोग नहीं कर रहे हैं। इसलिए उपयोगकर्ताओं को कुछ प्रकार के एसडीके प्रदान करना एक अच्छा विचार हो सकता है ताकि कम से कम उन्हें स्वयं इसके माध्यम से न जाना पड़े। यदि आपको इसे इस तरह करने की आवश्यकता है, तो मुझे सुरक्षा स्तर उचित लगता है (बस-राइट-किल)।

गुप्त भंडारण सुरक्षित

यह निर्भर करता है कि आप किसे विफल करना चाहते हैं। यदि आप उपयोगकर्ता के नाम में अपनी REST सेवा का उपयोग करने से उपयोगकर्ता के फ़ोन तक पहुँचने से लोगों को रोक रहे हैं, तो लक्ष्य OS पर किसी प्रकार की कीरिंग API को खोजना और SDK (या कार्यान्वयनकर्ता) को स्टोर करना अच्छा होगा। वहाँ कुंजी। यदि यह संभव नहीं है, तो आप कम से कम इसे एन्क्रिप्ट करके गुप्त प्राप्त करने के लिए थोड़ा कठिन बना सकते हैं, और अलग-अलग स्थानों में एन्क्रिप्ट किए गए डेटा और एन्क्रिप्शन कुंजी को संग्रहीत कर सकते हैं।

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

(*) संपादित करें: एसएसएल कनेक्शन को अब उन्हें सत्यापित करने के लिए अतिरिक्त कदम उठाए बिना सुरक्षित नहीं माना जाना चाहिए


धन्यवाद cmc, सभी अच्छे अंक और विचार के लिए बढ़िया खाना। मैंने S3 REST API प्रमाणीकरण तंत्र की तरह, जैसा कि आपने ऊपर चर्चा की है, उसी तरह एक टोकन / HMAC दृष्टिकोण लेना समाप्त कर दिया है।
कैंटलिन

यदि आप सर्वर पर टोकन कैश करते हैं, तो क्या यह अनिवार्य रूप से अच्छे पुराने सत्र आईडी के समान नहीं है? सत्र आईडी अल्पकालिक है और यह हर अनुरोध पर अपने डीबी से टकराने से बचने के लिए फास्ट कैश स्टोरेज (यदि आप इसे लागू करते हैं) से जुड़ा हुआ है। ट्रू रेस्टफुल और स्टेटलेस डिज़ाइन में सेशन नहीं होना चाहिए, लेकिन अगर आप एक आईडी के रूप में एक टोकन का उपयोग कर रहे हैं और फिर भी डीबी को हिट कर रहे हैं, तो क्या यह बेहतर नहीं होगा कि आप सत्र आईडी का उपयोग करें? वैकल्पिक रूप से, आप JSON वेब टोकन के लिए जा सकते हैं जिसमें सही स्टेटलेस डिज़ाइन के लिए संपूर्ण सत्र डेटा के लिए एन्क्रिप्टेड या हस्ताक्षरित जानकारी है।
जस्टमार्टिन

16

शुद्ध रेस्टफुल एपीआई को अंतर्निहित प्रोटोकॉल मानक सुविधाओं का उपयोग करना चाहिए:

  1. HTTP के लिए, RESTful API को मौजूदा HTTP मानक हेडर का पालन करना चाहिए। एक नया HTTP हेडर जोड़ना REST सिद्धांतों का उल्लंघन करता है। पहिया का फिर से आविष्कार न करें, HTTP / 1.1 मानकों में सभी मानक सुविधाओं का उपयोग करें - जिसमें स्थिति प्रतिक्रिया कोड, हेडर, और इसी तरह शामिल हैं। RESTFul वेब सेवाओं का लाभ उठाने और HTTP मानकों पर भरोसा करना चाहिए।

  2. श्रेष्ठ सेवाएँ आवश्यक होनी चाहिए। कोई भी ट्रिक, जैसे टोकन आधारित प्रमाणीकरण जो सर्वर पर पिछले REST अनुरोधों की स्थिति को याद रखने का प्रयास करता है, REST सिद्धांतों का उल्लंघन करता है। फिर, यह एक जरूरी है; यदि आप वेब सर्वर सर्वर पर किसी भी प्रकार के सत्र को स्थापित करने के प्रयास में सर्वर पर किसी भी अनुरोध / प्रतिक्रिया संदर्भ से संबंधित जानकारी को सहेजते हैं, तो आपकी वेब सेवा स्टेटलेस नहीं है। और अगर यह स्टेटलेस नहीं है तो यह RESTFul नहीं है।

नीचे-पंक्ति: प्रमाणीकरण / प्राधिकरण उद्देश्यों के लिए आपको HTTP मानक प्राधिकरण शीर्ष लेख का उपयोग करना चाहिए। यही है, आपको प्रत्येक बाद के अनुरोध में HTTP प्राधिकरण / प्रमाणीकरण शीर्षलेख जोड़ना चाहिए जिसे प्रमाणित करने की आवश्यकता है। REST API को HTTP प्रमाणीकरण योजना मानकों का पालन करना चाहिए। इस शीर्षलेख को कैसे स्वरूपित किया जाना चाहिए इसकी बारीकियों को RFC 2616 HTTP 1.1 मानकों में परिभाषित किया गया है - RFC 2616 का अनुभाग 14.8 प्राधिकरण, और RFC 2617 HTTP प्रमाणीकरण में: मूल और डाइजेस्ट एक्सेस प्रमाणीकरण। ।

मैंने सिस्को प्राइम परफॉर्मेंस मैनेजर एप्लिकेशन के लिए एक RESTful सेवा विकसित की है। REST API का दस्तावेज है कि मैं शोकहारा एपीआई अनुपालन के बारे में अधिक जानकारी के लिए है कि आवेदन के लिए लिखा था के लिए खोज गूगल यहाँ । उस कार्यान्वयन में, मैंने HTTP "बेसिक" प्राधिकरण योजना का उपयोग करने के लिए चुना है। - उस REST API दस्तावेज़ के संस्करण 1.5 या उससे ऊपर के संस्करण की जाँच करें, और दस्तावेज़ में प्राधिकरण की खोज करें।


8
"नया HTTP हेडर जोड़ने से REST सिद्धांतों का उल्लंघन होता है" ऐसा कैसे? और यदि आप इस पर हैं, तो आप यह समझाने के लिए बहुत दयालु हो सकते हैं कि एक निश्चित अवधि के बाद समाप्त होने वाले एक पासवर्ड और एक निश्चित अवधि के बाद समाप्त होने वाले टोकन के बीच वास्तव में अंतर (सिद्धांतों के बारे में) क्या है।
एक बेहतर जैतून

6
उपयोगकर्ता नाम + पासवर्ड एक टोकन (!) है जो ग्राहक और सर्वर के बीच हर अनुरोध पर आदान-प्रदान किया जाता है। यह टोकन सर्वर पर बना रहता है और इसमें समय-समय पर लाइव होता है। यदि पासवर्ड समाप्त हो जाता है तो मुझे एक नया अधिग्रहण करना होगा। आप "टोकन" को "सर्वर सत्र" के साथ जोड़ते हैं, लेकिन यह एक अमान्य निष्कर्ष है। यह भी अप्रासंगिक है क्योंकि यह एक कार्यान्वयन विवरण होगा। उपयोगकर्ता नाम / पासवर्ड के अलावा टोकन का आपका वर्गीकरण स्टेटफुल होने के नाते विशुद्ध रूप से कृत्रिम है, इहो।
एक बेहतर जैतून

1
मुझे लगता है कि आपको मूल प्रमाणीकरण पर पुनर्स्थापना के साथ कार्यान्वयन करने के लिए प्रेरित करना चाहिए जो मूल प्रश्न का हिस्सा है। हो सकता है कि आप कोड के साथ कुछ अच्छे उदाहरणों से भी जुड़ सकते हैं। इस विषय में एक शुरुआत के रूप में सिद्धांत बहुत सारे अच्छे संसाधनों के साथ पर्याप्त स्पष्ट लगता है, लेकिन कार्यान्वयन विधि नहीं है और उदाहरण जटिल हैं। मुझे यह निराशा होती है कि ऐसा लगता है कि कस्टम कोडिंग को समयबद्ध तरीके से लागू करने के लिए ऐसा लगता है जो हजारों बार किया गया है।
जेपीके

13
-1 "कोई भी ट्रिक, जैसे कि टोकन-आधारित प्रमाणीकरण जो सर्वर पर पिछले REST अनुरोधों की स्थिति को याद रखने का प्रयास करता है, जो कि रस्म सिद्धांतों का उल्लंघन करता है।" टोकन आधारित प्रमाणीकरण का पिछले REST अनुरोधों की स्थिति से कोई लेना-देना नहीं है और यह REST की वैधानिकता का उल्लंघन नहीं करता है
केरम बेयडोआन

1
तो, इसके अनुसार, JSON वेब टोकन REST उल्लंघन है क्योंकि वे उपयोगकर्ता के राज्य (दावे) को स्टोर कर सकते हैं? वैसे भी, मैं REST का उल्लंघन करना और "टोकन" के रूप में अच्छे पुराने सत्र की आईडी का उपयोग करना पसंद करता हूं, लेकिन प्रारंभिक प्रमाणीकरण उपयोगकर्ता नाम के साथ किया जाता है, साझा गुप्त और बहुत कम समय तक रहने वाले टाइमस्टैम्प का उपयोग करके हस्ताक्षरित या एन्क्रिप्ट किया जाता है (इसलिए यह विफल रहता है अगर कोई फिर से खेलना करने की कोशिश करता है उस)। "एंटरप्राइज-ईश" एप्लिकेशन में सत्र लाभ को फेंकना मुश्किल है (लगभग हर अनुरोध में आवश्यक कुछ डेटा के लिए डेटाबेस को टालने से बचने के लिए), इसलिए कभी-कभी हमें सच्चे स्टेटलेसनेस का त्याग करना पड़ता है।
जस्टआमार्टिन

2

वेब में एक स्टेटफुल प्रोटोकॉल एक अस्थायी टोकन होता है जो ब्राउज़र और सर्वर (कुकी हेडर या यूआरआई पुनर्लेखन के माध्यम से) के बीच हर अनुरोध पर एक्सचेंज किया जाता है। यह टोकन आमतौर पर सर्वर के अंत में बनाया जाता है, और यह अपारदर्शी डेटा का एक टुकड़ा होता है जिसमें एक निश्चित समय-समय पर लाइव होता है, और इसका एक विशिष्ट वेब उपयोगकर्ता एजेंट की पहचान करने का एकमात्र उद्देश्य होता है। यही है, टोकन अस्थायी है, और एक स्टेट हो जाता है कि वेब सर्वर को उस वार्तालाप की अवधि के दौरान क्लाइंट उपयोगकर्ता एजेंट की ओर से बनाए रखना होगा। इसलिए, इस तरह से टोकन का उपयोग करने वाला संचार STATEFUL है। और अगर क्लाइंट और सर्वर के बीच बातचीत STATEFUL है तो यह RESTful नहीं है।

उपयोगकर्ता नाम / पासवर्ड (प्राधिकरण हेडर पर भेजा गया) आमतौर पर डेटाबेस पर उपयोगकर्ता की पहचान करने के इरादे से बना रहता है। कभी-कभी उपयोगकर्ता एक और एप्लिकेशन का मतलब हो सकता है; हालाँकि, उपयोगकर्ता नाम / पासवर्ड एक विशिष्ट वेब क्लाइंट उपयोगकर्ता एजेंट की पहचान करने के लिए कभी नहीं है । प्राधिकरण शीर्षक (HTTP बेसिक ऑथराइजेशन के बाद) में उपयोगकर्ता नाम / पासवर्ड का उपयोग करने पर आधारित एक वेब एजेंट और सर्वर के बीच की बातचीत STATELESS है क्योंकि वेब सर्वर फ्रंट-एंड किसी भी स्टेट सूचना को बना या बनाए नहीं रख रहा है।जो भी एक विशिष्ट वेब क्लाइंट उपयोगकर्ता एजेंट की ओर से। और REST की मेरी समझ के आधार पर, प्रोटोकॉल में स्पष्ट रूप से कहा गया है कि क्लाइंट और सर्वर के बीच की बातचीत स्टेटलेस होनी चाहिए। इसलिए, अगर हम एक सच्ची सेवा चाहते हैं, तो हमें हर एक कॉल के लिए प्राधिकरण हेडर में उपयोगकर्ता नाम / पासवर्ड (मेरी पिछली पोस्ट में उल्लेखित RFC का उल्लेख करें) का उपयोग करना चाहिए, न कि एक प्रकार का टोकन (जैसे वेब सर्वर में बनाया गया सत्र टोकन) , प्राधिकरण सर्वर में निर्मित OAuth टोकन, और इसी तरह)।

मैं समझता हूं कि कई REST प्रदाता OAuth1 या OAuth2 स्वीकार-टोकन जैसे टोकन का उपयोग HTTP हेडर में "प्राधिकरण: बियरर" के रूप में पारित करने के लिए कर रहे हैं। हालाँकि, यह मुझे प्रतीत होता है कि रेस्टफुल सेवाओं के लिए उन टोकन का उपयोग करने से वास्तविक स्थिति का उल्लंघन होता है, जिसका अर्थ है कि आरईएसटी ने गले लगाया; क्योंकि वे टोकन उस वेब क्लाइंट / सर्वर वार्तालाप की वैध अवधि के लिए एक विशिष्ट वेब क्लाइंट उपयोगकर्ता एजेंट की पहचान करने के लिए सर्वर साइड पर बनाए गए / बनाए गए डेटा के अस्थायी टुकड़े हैं । इसलिए, कोई भी सेवा जो उन OAuth1 / 2 टोकन का उपयोग कर रही है, उन्हें REST नहीं कहा जाना चाहिए यदि हम एक STATELESS प्रोटोकॉल के TRUE अर्थ से चिपके रहना चाहते हैं।

रूबेंस

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.