यूजर क्रेडेंशियल्स के आधार पर API गेटवे के साथ डायनामिक रूटिंग
April 9, 2023
JWT क्लेम पर आधारित डायनामिक रूटिंग Apache APISIX और Okta के साथ
डायनामिक रूटिंग अधिकांश आधुनिक API गेटवे की एक शक्तिशाली सुविधा है जो आपको विभिन्न मानदंडों जैसे HTTP हेडर, क्वेरी पैरामीटर, या यहां तक कि अनुरोध बॉडी के आधार पर आने वाले अनुरोधों को वास्तविक समय में विभिन्न बैकएंड सेवाओं पर रूट करने की अनुमति देती है।
Apache APISIX के मौजूदा बिल्ट-इन प्लगइन्स का उपयोग करके, डेवलपर्स डायनामिक रूटिंग नियम भी बना सकते हैं जो विभिन्न उपयोगकर्ता क्रेडेंशियल्स जैसे एक्सेस टोकन, API कुंजी, या उपयोगकर्ता ID पर आधारित होते हैं। इस लेख में, हम Apache APISIX के साथ प्रमाणीकरण विशेषताओं पर आधारित डायनामिक रूटिंग को अपनाने के लाभों का पता लगाएंगे और आपको JWT टोकन के क्लेम पर आधारित क्लाइंट अनुरोधों को जिम्मेदार बैकएंड सेवाओं पर डायनामिक रूप से रूट करने का एक उदाहरण कॉन्फ़िगरेशन दिखाएंगे।
सीखने के उद्देश्य
आप इस लेख के माध्यम से निम्नलिखित सीखेंगे:
- API गेटवे के साथ ट्रैफ़िक को डायनामिक रूप से रूट करना।
- उपयोगकर्ता क्रेडेंशियल्स पर आधारित डायनामिक रूटिंग की आवश्यकता क्यों है?
- Apache APISIX के साथ JWT टोकन के क्लेम पर आधारित डायनामिक रूटिंग।
API गेटवे: ट्रैफ़िक को डायनामिक रूप से रूट करना
API गेटवे के साथ ट्रैफ़िक को डायनामिक रूप से रूट करने का उपयोग प्रदर्शन को अनुकूलित करने, सुरक्षा में सुधार करने और यह सुनिश्चित करने के लिए किया जा सकता है कि उपयोगकर्ताओं को उचित संसाधनों तक पहुंच हो।
डायनामिक रूटिंग के माध्यम से, एक सिस्टम विभिन्न सर्वरों या सेवाओं के बीच लोड को संतुलित कर सकता है। यह उच्च उपलब्धता सुनिश्चित करने में मदद कर सकता है क्योंकि ट्रैफ़िक को उपलब्ध सेवाओं या सर्वरों पर रूट किया जा सकता है। यदि एक सेवा या सर्वर विफल हो जाता है, तो ट्रैफ़िक को स्वचालित रूप से किसी अन्य उपलब्ध सेवा या सर्वर पर रीरूट किया जा सकता है।

डायनामिक रूटिंग का उपयोग उपयोगकर्ता के जियोलोकेशन के आधार पर ट्रैफ़िक को रूट करने के लिए भी किया जा सकता है। यह सुनिश्चित करने में मदद कर सकता है कि उपयोगकर्ता निकटतम सर्वर या सेवा से जुड़े हों, जिससे प्रतिक्रिया समय में सुधार हो और विलंबता कम हो।

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

डेमो: JWT टोकन के क्लेम पर आधारित डायनामिक रूटिंग
इस डेमो में, हम Conference API नामक एक मौजूदा सार्वजनिक बैकएंड API का उपयोग करते हैं जिसमें कॉन्फ्रेंस सत्र, वक्ता और विषय जानकारी होती है। वास्तविकता में, यह आपकी बैकएंड सेवा हो सकती है। मान लीजिए कि हम केवल उन सत्रों को फ़िल्टर और पुनर्प्राप्त करना चाहते हैं जो एक विशिष्ट वक्ता से संबंधित हैं जो अपने क्रेडेंशियल्स जैसे JWT टोकन का उपयोग करके सिस्टम में लॉग इन है। उदाहरण के लिए, https://conferenceapi.azurewebsites.net/speaker/1/sessions
अनुरोध केवल एक विशिष्ट वक्ता के सत्र दिखाता है जिसका एक अद्वितीय ID होता है और यह अद्वितीय ID JWT टोकन क्लेम के पेलोड के हिस्से के रूप में आता है। नीचे डिकोड किए गए टोकन पेलोड संरचना को देखें, इसमें एक speakerId फ़ील्ड भी शामिल है:

इस परिदृश्य में, हम API गेटवे पर एक ही रूट पर अनुरोध भेजते हैं और यह प्राधिकरण हेडर से डायनामिक URI की गणना करता है और अनुरोध को URI पर आगे भेजता है (नीचे दिए गए डायग्राम को समझने के लिए देखें)। ऐसा करने के लिए, हम निम्नलिखित प्लगइन्स का उपयोग करके Apache APISIX API गेटवे स्तर पर JWT टोकन के क्लेम पर आधारित डायनामिक रूटिंग को लागू करने जा रहे हैं:
- openid-connect प्लगइन जो आइडेंटिटी प्रोवाइडर (IdP) के साथ इंटरैक्ट करता है और बैकएंड एप्लिकेशन्स को अनप्रमाणित अनुरोधों को समय पर इंटरसेप्ट कर सकता है। एक आइडेंटिटी प्रोवाइडर के रूप में, हम Okta का उपयोग करते हैं जो हमारे कस्टम क्लेम के साथ एक JWT टोकन जारी करता है और JWT टोकन को वैलिडेट करता है। या आप अन्य IdPs जैसे Keycloak, और Ory Hydra, या यहां तक कि jwt-plugin का उपयोग करके एक JWT टोकन बना सकते हैं, और अनुरोधों को प्रमाणित और अधिकृत कर सकते हैं।
- serverless-pre-function प्लगइन एक कस्टम Lua फ़ंक्शन कोड लिखने के लिए जो अनुरोध को इंटरसेप्ट करता है, JWT टोकन क्लेम को डिकोड और पार्स करता है और क्लेम के मान को एक नए कस्टम हेडर में स्टोर करता है ताकि आगे प्राधिकरण निर्णय लिए जा सकें।
- proxy-rewrite प्लगइन, एक बार जब हमारे पास हेडर में क्लेम होता है, तो हम इस प्लगइन का उपयोग अनुरोध फॉरवर्डिंग मैकेनिज्म के रूप में करते हैं ताकि यह तय किया जा सके कि Nginx हेडर वेरिएबल के आधार पर कौन सा URI पथ उपयोग किया जाना चाहिए, हमारे मामले में यह
speakerIdहै जो विभिन्न पथ/speaker/$http_speakerId/sessionsबनाने के लिए डायनामिक रूप से बदलता है। प्लगइन अनुरोध को Conference API में संबंधित संसाधन पर फॉरवर्ड करेगा।
एक बार जब हम समझ गए कि हम डेमो के दौरान क्या कवर करने जा रहे हैं, तो आइए उपरोक्त परिदृश्य को कॉन्फ़िगर करने और ट्यूटोरियल को पूरा करने के लिए आवश्यक शर्तों की जांच करें।
आवश्यक शर्तें
- Docker का उपयोग कंटेनराइज्ड etcd और APISIX स्थापित करने के लिए किया जाता है।
- curl का उपयोग APISIX को रूट, अपस्ट्रीम और प्लगइन कॉन्फ़िगरेशन के लिए अनुरोध भेजने के लिए किया जाता है। आप API के साथ इंटरैक्ट करने के लिए Postman जैसे आसान टूल्स का भी उपयोग कर सकते हैं।
- Apache APISIX आपके लक्ष्य वातावरण में स्थापित है। APISIX को निम्नलिखित क्विक स्टार्ट गाइड के साथ आसानी से स्थापित और शुरू किया जा सकता है।
- सुनिश्चित करें कि आपका OKTA अकाउंट बन गया है, आपने एक नया ऐप रजिस्टर किया है (आप इस गाइड का पालन कर सकते हैं Configuring Okta), टोकन में एक कस्टम क्लेम जोड़ें Okta डैशबोर्ड का उपयोग करके, और एक टोकन का अनुरोध करें जिसमें कस्टम क्लेम हो जिसे
speakerIdकहा जाता है।
बैकएंड सेवा (अपस्ट्रीम) को कॉन्फ़िगर करें
आपको Conference API के लिए बैकएंड सेवा को कॉन्फ़िगर करने की आवश्यकता होगी जिस पर आप अनुरोधों को रूट करना चाहते हैं। यह Apache APISIX में Admin API के माध्यम से एक अपस्ट्रीम सर्वर जोड़कर किया जा सकता है।
curl "http://127.0.0.1:9180/apisix/admin/upstreams/1" -X PUT -d ' { "name": "Conferences API upstream", "desc": "Register Conferences API as the upstream", "type": "roundrobin", "scheme": "https", "nodes": { "conferenceapi.azurewebsites.net:443": 1 } }'
एक प्लगइन कॉन्फ़िग बनाएं
अगला, हम एक नया प्लगइन कॉन्फ़िग ऑब्जेक्ट सेट अप करते हैं। हम 3 प्लगइन्स openid-connect, serverless-pre-function और proxy-rewrite का उपयोग करेंगे जैसा कि हमने पहले प्रत्येक प्लगइन के उपयोग के मामलों पर चर्चा की है। आपको केवल openid-connect प्लगइन विशेषताओं (ClienID, Secret, Discovery और Introspection endpoints) को अपने Okta विवरणों से बदलने की आवश्यकता है इससे पहले कि आप curl कमांड को निष्पादित करें।
curl "http://127.0.0.1:9180/apisix/admin/plugin_configs/1" -X PUT -d ' { "plugins": { "openid-connect":{ "client_id":"{YOUR_OKTA_CLIENT_ID}", "client_secret":"{YOUR_OKTA_CLIENT_SECRET}", "discovery":"https://{YOUR_OKTA_ISSUER}/oauth2/default/.well-known/openid-configuration", "scope":"openid", "bearer_only":true, "realm":"master", "introspection_endpoint_auth_method":"https://{YOUR_OKTA_ISSUER}/oauth2/v1/introspect", "redirect_uri":"https://conferenceapi.azurewebsites.net/" }, "proxy-rewrite": { "uri": "/speaker/$http_speakerId/sessions", "host":"conferenceapi.azurewebsites.net" }, "serverless-pre-function": { "phase": "rewrite", "functions" : ["return function(conf, ctx) -- Import neccessary libraries local core = require(\"apisix.core\") local jwt = require(\"resty.jwt\") -- Retrieve the JWT token from the Authorization header local jwt_token = core.request.header(ctx, \"Authorization\") if jwt_token ~= nil then -- Remove the Bearer prefix from the JWT token local _, _, jwt_token_only = string.find(jwt_token, \"Bearer%s+(.+)\") if jwt_token_only ~= nil then -- Decode the JWT token local jwt_obj = jwt:load_jwt(jwt_token_only) if jwt_obj.valid then -- Retrieve the value of the speakerId claim from the JWT token local speakerId_claim_value = jwt_obj.payload.speakerId -- Store the speakerId claim value in the header variable core.request.set_header(ctx, \"speakerId\", speakerId_claim_value) end end end end "]} } }'
उपरोक्त कॉन्फ़िग में, सबसे कठिन हिस्सा समझने के लिए serverless-pre-function प्लगइन के अंदर लिखा गया कस्टम फ़ंक्शन कोड हो सकता है:
return function(conf, ctx) -- Import neccessary libraries local core = require(\"apisix.core\") local jwt = require(\"resty.jwt\") -- Retrieve the JWT token from the Authorization header local jwt_token = core.request.header(ctx, \"Authorization\") if jwt_token ~= nil then -- Remove the Bearer prefix from the JWT token local _, _, jwt_token_only = string.find(jwt_token, \"Bearer%s+(.+)\") if jwt_token_only ~= nil then -- Decode the JWT token local jwt_obj = jwt:load_jwt(jwt_token_only) if jwt_obj.valid then -- Retrieve the value of the speakerId claim from the JWT token local speakerId_claim_value = jwt_obj.payload.speakerId -- Store the speakerId claim value in the header variable core.request.set_header(ctx, \"speakerId\", speakerId_claim_value) end end end end
मूल रूप से, यह प्लगइन अन्य दो प्लगइन्स से पहले निष्पादित होगा और यह निम्नलिखित करता है:
- प्राधिकरण हेडर से JWT टोकन को पुनर्प्राप्त करता है।
- JWT टोकन से "Bearer " प्रीफ़िक्स को हटाता है।
- resty.jwt लाइब्रेरी का उपयोग करके JWT टोकन को डिकोड करता है।
- डिकोड किए गए JWT टोकन से "speakerId" क्लेम का मान पुनर्प्राप्त करता है।
- अंत में, यह "speakerId" क्लेम के मान को speakerId हेडर वेरिएबल में स्टोर करता है।
एक नया रूट कॉन्फ़िगर करें
इस चरण में एक नया रूट सेट अप करना शामिल है जो प्लगइन कॉन्फ़िग का उपयोग करता है, और रूट को अपस्ट्रीम के साथ काम करने के लिए कॉन्फ़िगर करता है (उनके ID का संदर्भ देकर) जो हमने पिछले चरणों में बनाया था:
curl "http://127.0.0.1:9180/apisix/admin/routes/1" -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "name":"Conferences API speaker sessions route", "desc":"Create a new route in APISIX for the Conferences API speaker sessions", "methods": ["GET"], "uri": "/sessions", "upstream_id":"1", "plugin_config_id":1 }'
उपरोक्त कॉन्फ़िगरेशन में, हमने रूट मिलान नियमों को परिभाषित किया है जैसे केवल HTTP GET अनुरोध URI /sessions पर सही बैकएंड सेवा पर रूट किए जाएंगे।
Okta से एक टोकन प्राप्त करें
APISIX साइड पर अपस्ट्रीम, प्लगइन्स और रूट को कॉन्फ़िगर करने के बाद, अब हम Okta से एक टोकन का अनुरोध करते हैं जिसमें हमारा speakerId कस्टम क्लेम होता है। आप इस गाइड का पालन कर सकते हैं जिसमें टोकन का अनुरोध करने के लिए URL बनाने के बारे में जानकारी शामिल है या बस नीचे दिए गए परिणामी URL का उपयोग करें जिसमें आपका Okta issuer और client id होता है:
https://{YOUR_OKTA_ISSUER}/oauth2/default/v1/authorize?client_id={YOUR_OKTA_CLIENT_ID} &response_type=id_token &scope=openid &redirect_uri=https%3A%2F%2Fconferenceapi.azurewebsites.net &state=myState &nonce=myNonceValue
जब आप अनुरोध को अपने ब्राउज़र में पेस्ट करते हैं, तो ब्राउज़र आपके Okta के लिए साइन-इन पेज पर रीडायरेक्ट हो जाता है और एक ID टोकन जनरेट करता है।
https://conferenceapi.azurewebsites.net/#id_token={TOKEN_WILL_BE_HERE}
ध्यान दें कि टोकन प्राप्त करने की प्रक्रिया अन्य आइडेंटिटी प्रोवाइडर्स से अलग हो सकती है।
वापस आए ID टोकन की जांच करने के लिए, आप मान को कॉपी करके किसी भी JWT डिकोडर (उदाहरण के लिए, https://token.dev) में पेस्ट कर सकते हैं।
डायनामिक रूटिंग का परीक्षण करें
अंत में, अब हम यह सत्यापित कर सकते हैं कि अनुरोध को मिलान मानदंड और JWT टोकन क्लेम के आधार पर सही URI पथ (वक्ता-विशिष्ट सत्रों के साथ) पर रूट किया जा रहा है, एक और सरल curl कमांड चलाकर:
curl -i -X "GET [http://127.0.0.1:9080/sessions](http://127.0.0.1:9080/sessions)" -H "Authorization: Bearer {YOUR_OKTA_JWT_TOKEN}"
यहां हम चलते हैं, परिणाम जैसा हमने अपेक्षा की थी। यदि हमने Okta JWT क्लेम में speakerId को 1 पर सेट किया है, तो Apisix ने अनुरोध को संबंधित URI पथ पर रूट किया और प्रतिक्रिया में इस वक्ता के सभी सत्र लौटाए।
{ "collection": { "version": "1.0", "links": [], "items": [ { "href": "https://conferenceapi.azurewebsites.net/session/114", "data": [ { "name": "Title", "value": "\r\n\t\t\tIntroduction to Windows Azure Part I\r\n\t\t" }, { "name": "Timeslot", "value": "04 December 2013 13:40 - 14:40" }, { "name": "Speaker", "value": "Scott Guthrie" } ], "links": [ { "rel": "http://tavis.net/rels/speaker", "href": "https://conferenceapi.azurewebsites.net/speaker/1" }, { "rel": "http://tavis.net/rels/topics", "href": "https://conferenceapi.azurewebsites.net/session/114/topics" } ] }, { "href": "https://conferenceapi.azurewebsites.net/session/121", "data": [ { "name": "Title", "value": "\r\n\t\t\tIntroduction to Windows Azure Part II\r\n\t\t" }, { "name": "Timeslot", "value": "04 December 2013 15:00 - 16:00" }, { "name": "Speaker", "value": "Scott Guthrie" } ], } ] } }
टेकअवे
- API गेटवे के साथ, आप विभिन्न मानदंडों के आधार पर ट्रैफ़िक को विभिन्न बैकएंड सेवाओं पर रूट कर सकते हैं।
- डायनामिक रूटिंग अनुरोध हेडर, क्वेरी, या बॉडी में निर्दिष्ट उपयोगकर्ता विशेषताओं के आधार पर प्राप्त की जा सकती है।
- आप जटिल रूटिंग नियम बना सकते हैं जो JWT टोकन में मौजूद क्लेम को ध्यान में रखते हैं, और यह सुनिश्चित करते हैं कि केवल अधिकृत अनुरोधों को आपके API तक पहुंचने की अनुमति हो।