استخدام نطاقات OAuth2

أنت الآن بصدد الاطّلاع على مستندات Apigee Edge.
انتقِل إلى مستندات Apigee X.
info

يتناول هذا الموضوع كيفية استخدام نطاقات OAuth 2.0 على Apigee Edge.

ما هو نطاق OAuth2؟

توفّر نطاقات OAuth 2.0 طريقة للحدّ من مقدار الوصول الممنوح لرمز دخول. على سبيل المثال، قد يتم منح رمز الدخول الصادر إلى تطبيق عميل إذن الوصول للقراءة والكتابة إلى الموارد المحمية، أو إذن الوصول للقراءة فقط. يمكنك تنفيذ واجهات برمجة التطبيقات لفرض أي نطاق أو مجموعة من النطاقات التي تريدها. لذلك، إذا تلقّى برنامج رمزًا مميّزًا يتضمّن نطاق READ، وحاول استدعاء نقطة نهاية لواجهة برمجة تطبيقات تتطلّب إذن الوصول WRITE، سيتعذّر الاستدعاء.

في هذا الموضوع، سنتناول كيفية تحديد النطاقات لرموز الدخول المميزة وكيفية فرض Apigee Edge لنطاقات OAuth 2.0. بعد قراءة هذا الموضوع، ستتمكّن من استخدام النطاقات بثقة.

كيف يتم تحديد النطاقات لرموز الدخول؟

عندما ينشئ Edge رمز دخول مميزًا، قد يحدّد نطاقًا لهذا الرمز. لفهم كيفية حدوث ذلك، يجب أولاً أن تكون على دراية بعناصر Apigee Edge التالية: منتجات واجهة برمجة التطبيقات والمطوّرون وتطبيقات المطوّرين. للحصول على مقدّمة، يُرجى الاطّلاع على مقدّمة حول النشر. ننصحك بمراجعة هذه المادة إذا كنت بحاجة إلى ذلك قبل المتابعة.

رمز الدخول هو سلسلة طويلة من الأحرف العشوائية التي تسمح لـ Edge بالتحقّق من طلبات واجهة برمجة التطبيقات الواردة (يمكنك اعتبارها بديلاً عن بيانات اعتماد اسم المستخدم/كلمة المرور النموذجية). من الناحية الفنية، الرمز المميّز هو مفتاح يشير إلى مجموعة من البيانات الوصفية التي تبدو على النحو التالي:

{
  "issued_at" : "1416962591727",
  "application_name" : "0d3e1d41-a59f-4d74-957e-d4e3275d4781",
  "scope" : "A",
  "status" : "approved",
  "api_product_list" : "[scopecheck1-bs0cSuqS9y]",
  "expires_in" : "1799", //--in seconds
  "developer.email" : "scopecheck1-AdBmANhsag@apigee.com",
  "organization_id" : "0",
  "token_type" : "BearerToken",
  "client_id" : "eTtB7w5lvk3DnOZNGReBlvGvIAeAywun",
  "access_token" : "ODm47ris5AlEty8TDc1itwYPe5MW",
  "organization_name" : "wwitman",
  "refresh_token_expires_in" : "0", //--in seconds
  "refresh_count" : "0"
}

تتضمّن البيانات الوصفية للرمز المميّز سلسلة رمز الدخول الفعلي ومعلومات انتهاء الصلاحية ومعلومات تعريفية عن تطبيق المطوّر والمطوّر والمنتجات المرتبطة بالرمز المميّز. ستلاحظ أيضًا أنّ البيانات الوصفية تتضمّن "النطاق".

كيف يحصل الرمز المميّز على نطاقه؟

أول مفتاح لفهم النطاق هو تذكُّر أنّه يمكن أن يتضمّن كل منتج في تطبيق المطوّر صفر نطاقات أو أكثر. يمكن تعيين هذه النطاقات عند إنشاء المنتج، أو يمكن إضافتها لاحقًا. وهي تظهر كقائمة أسماء ويتم تضمينها في "البيانات الوصفية" المرتبطة بكل منتج.

عند إنشاء تطبيق مطوِّر وإضافة منتجات إليه، يبحث Edge في جميع المنتجات في تطبيق المطوِّر وينشئ قائمة بجميع النطاقات الخاصة بهذه المنتجات (قائمة النطاقات الرئيسية أو العامة للتطبيق، وهي عبارة عن اتحاد لجميع النطاقات المعترف بها).

عندما يطلب تطبيق عميل رمز دخول من Apigee Edge، يمكنه اختياريًا تحديد النطاقات التي يريد ربطها بهذا الرمز. على سبيل المثال، يطلب الطلب التالي النطاق "أ". أي أنّ العميل يطلب من خادم المصادقة (Edge) إنشاء رمز دخول يتضمّن النطاق "أ" (ما يمنح التطبيق الإذن باستدعاء واجهات برمجة التطبيقات التي تتضمّن النطاق "أ"). يرسل التطبيق طلب POST على النحو التالي:

curl -i -X POST -H Authorization: Basic Mg12YTk2UkEIyIBCrtro1QpIG -H content-type:application/x-www-form-urlencoded http://myorg-test.apigee.net/oauth/token?grant_type=client_credentials&scope=A

الإجراء

عندما يتلقّى Edge هذا الطلب، يعرف التطبيق الذي يقدّم الطلب ويعرف تطبيق المطوّر الذي سجّله العميل (يتم ترميز معرّف العميل ومفاتيح سر العميل في عنوان المصادقة الأساسية). بما أنّ مَعلمة طلب البحث scope مضمّنة، يجب أن يقرّر Edge ما إذا كان أي من منتجات واجهة برمجة التطبيقات المرتبطة بتطبيق المطوّر يتضمّن النطاق "A". وفي حال توفُّرها، يتم إنشاء رمز دخول مميز بالنطاق "أ". يمكن النظر إلى ذلك بطريقة أخرى، وهي أنّ مَعلمة طلب البحث الخاصة بالنطاق هي نوع من الفلاتر. إذا كان تطبيق المطوّر يتعرّف على النطاقات "أ، ب، س"، وكانت مَعلمة طلب البحث تحدّد "scope=س ص ع"، سيتم تعيين النطاق "س" فقط للرمز المميّز.

ماذا يحدث إذا لم يُرفق العميل مَعلمة نطاق؟ في هذه الحالة، ينشئ Edge رمزًا مميزًا يتضمّن جميع النطاقات التي يتعرّف عليها تطبيق المطوّر. من المهم معرفة أنّ السلوك التلقائي هو عرض رمز دخول يتضمّن اتحاد جميع النطاقات لجميع المنتجات المضمّنة في تطبيق المطوّر.

إذا لم يحدّد أي من المنتجات المرتبطة بتطبيق أحد المطوّرين نطاقات، وكان الرمز المميّز يتضمّن نطاقًا، ستتعذّر المكالمات التي يتم إجراؤها باستخدام هذا الرمز المميّز.

لنفترض أنّ تطبيقًا للمطوّر يتعرّف على النطاقات التالية: أ ب ج د. هذه هي القائمة الرئيسية لنطاقات التطبيق. قد يكون أحد المنتجات في التطبيق له النطاقان A وB، بينما يكون للمنتج الثاني النطاقان C وD، أو أي مجموعة أخرى. إذا لم يحدّد العميل المَعلمة scope (أو إذا حدّد مَعلمة النطاق بدون قيمة)، سيتم منح الرمز المميّز جميع النطاقات الأربعة: A وB وC وD. مرة أخرى، يتلقّى الرمز المميّز مجموعة من النطاقات التي تمثّل اتحاد جميع النطاقات التي يتعرّف عليها تطبيق المطوّر.

هناك حالة أخرى يكون فيها السلوك التلقائي هو عرض رمز دخول يتضمّن جميع النطاقات المعروفة، وذلك عندما لا تحدّد سياسة GenerateAccessToken (سياسة Apigee Edge التي تنشئ رموز الدخول) عنصر <Scope>. على سبيل المثال، إليك سياسة GenerateAccessToken حيث تم تحديد <Scope> . في حال عدم توفّر العنصر <Scope> (أو إذا كان متوفّرًا ولكنّه فارغ)، سيتم تنفيذ السلوك التلقائي.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-GenerateAccessToken">
    <DisplayName>OAuthV2 - Generate Access Token</DisplayName>
    <Attributes>
      <Attribute name='hello' ref='system.time' display='false'>value1</Attribute>
    </Attributes>
    <Scope>request.queryparam.scope</Scope> 
    <GrantType>request.formparam.grant_type</GrantType>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>GenerateAccessToken</Operation>
    <SupportedGrantTypes>
      <GrantType>client_credentials</GrantType>
    </SupportedGrantTypes>
  <GenerateResponse enabled="true"/>
</OAuthV2>

كيف يتم فرض النطاقات؟

أولاً، تذكَّر أنّه في Apigee Edge، يتم التحقّق من صحة رموز الدخول باستخدام سياسة OAuthV2 (يتم وضعها عادةً في بداية مسار الخادم الوكيل). يجب أن تتضمّن السياسة عملية VerifyAccessToken. لنلقِ نظرة على هذه السياسة:

<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenA">
    <DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>VerifyAccessToken</Operation>
    <Scope>A</Scope> <!-- Optional: space-separated list of scope names. -->
    <GenerateResponse enabled="true"/>
</OAuthV2>

لاحظ عنصر <Scope>. ويُستخدَم لتحديد النطاقات التي ستقبلها السياسة.

في هذا المثال، لن تنجح السياسة إلا إذا كانت رمز الدخول يتضمّن النطاق "أ". في حال حذف عنصر <Scope> هذا أو عدم ضبط أي قيمة له، ستتجاهل السياسة نطاق رمز الدخول.

بفضل إمكانية التحقّق من صحة رموز الدخول استنادًا إلى النطاق، يمكنك تصميم واجهات برمجة التطبيقات لفرض نطاقات معيّنة. يمكنك إجراء ذلك من خلال تصميم مسارات مخصّصة تتضمّن سياسات VerifyAccessToken الواعية بالنطاق.

لنفترض أنّ واجهة برمجة التطبيقات تتضمّن مسارًا محدّدًا لنقطة النهاية /resourceA:

<Flow name="resourceA">
            <Condition>(proxy.pathsuffix MatchesPath "/resourceA") and (request.verb = "GET")</Condition>
            <Description>Get a resource A</Description>
            <Request>
                <Step>
                    <Name>OAuthV2-VerifyAccessTokenA</Name>
                </Step>
            </Request>
            <Response>
                <Step>
                    <Name>AssignMessage-CreateResponse</Name>
                </Step>
            </Response>
        </Flow>

عندما يتم تشغيل هذا المسار (يتم تلقّي طلب يتضمّن /resourceA في لاحقة المسار)، يتم استدعاء السياسة OAuthV2-VerifyAccessTokenA على الفور. تتحقّق هذه السياسة من أنّ رمز الدخول صالح، كما تتحقّق من النطاقات التي يتيحها الرمز. إذا تم ضبط السياسة كما في المثال أدناه، مع <Scope>A</Scope>، لن تنجح السياسة إلا إذا كانت الرمز المميز للوصول يتضمّن النطاق "A". وفي حال عدم توفّرها، سيتم عرض رسالة خطأ.

<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenA">
    <DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>VerifyAccessToken</Operation>
    <Scope>A</Scope>
    <GenerateResponse enabled="true"/>
</OAuthV2>

باختصار، يتحمّل مطوّرو واجهات برمجة التطبيقات مسؤولية تصميم عملية فرض النطاق في واجهات برمجة التطبيقات الخاصة بهم. ويتم ذلك من خلال إنشاء تدفقات مخصّصة للتعامل مع نطاقات محدّدة، وإرفاق سياسات VerifyAccessToken لفرض هذه النطاقات.

أمثلة على الرموز

أخيرًا، لنلقِ نظرة على بعض الأمثلة على طلبات البيانات من واجهة برمجة التطبيقات للمساعدة في توضيح كيفية حصول الرموز المميزة على نطاقات وكيفية فرض النطاقات.

حالة تلقائية

لنفترض أنّ لديك تطبيقًا للمطوّرين يتضمّن منتجات، وأنّ اتحاد نطاقات هذه المنتجات هو: أ، ب، ج. يطلب طلب البيانات من واجهة برمجة التطبيقات هذا رمز دخول، ولكنّه لا يحدّد مَعلمة طلب النطاق.

curl -X POST -H content-type:application/x-www-form-urlencoded http://wwitman-test.apigee.net/scopecheck1/token?grant_type=client_credentials

في هذه الحالة، سيتم منح الرمز المميّز الذي تم إنشاؤه النطاقات A وB وC (السلوك التلقائي). ستبدو بيانات الرمز المميز الوصفية على النحو التالي:

{
  "issued_at" : "1417016208588",
  "application_name" : "eb1a0333-5775-4116-9eb2-c36075ddc360",
  "scope" : "A B C",
  "status" : "approved",
  "api_product_list" : "[scopecheck1-yEgQbQqjRR]",
  "expires_in" : "1799", //--in seconds
  "developer.email" : "scopecheck1-yxiuHuZcDW@apigee.com",
  "organization_id" : "0",
  "token_type" : "BearerToken",
  "client_id" : "atGFvl3jgA0pJd05rXKHeNAC69naDmpW",
  "access_token" : "MveXpj4UYXol38thNoJYIa8fBGlI",
  "organization_name" : "wwitman",
  "refresh_token_expires_in" : "0", //--in seconds
  "refresh_count" : "0"
}

لنفترض الآن أنّ لديك نقطة نهاية لواجهة برمجة التطبيقات تتضمّن النطاق "أ" (أي أنّ VerifyAccessToken يتطلّب النطاق "أ"). في ما يلي سياسة VerifyAccessToken:

<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenA">
    <DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>VerifyAccessToken</Operation>
    <Scope>A</Scope>
    <GenerateResponse enabled="true"/>
</OAuthV2>

في ما يلي نموذج لطلب إلى نقطة نهاية تفرض النطاق A:

curl -X GET -H Authorization: Bearer MveXpj4UYXol38thNoJYIa8fBGlI http://wwitman-test.apigee.net/scopecheck1/resourceA 

تنجح مكالمة GET هذه:

 {
   "hello" : "Tue, 25 Nov 2014 01:35:53 UTC"
 }

تنجح العملية لأنّ سياسة VerifyAccessToken التي يتم تشغيلها عند استدعاء نقطة النهاية تتطلّب النطاق A، وتم منح رمز الدخول النطاقات A وB وC، وهو السلوك التلقائي.

حالة الفلترة

لنفترض أنّ لديك تطبيقًا للمطوّرين يتضمّن منتجات ذات نطاقات A وB وC وX. يمكنك طلب رمز دخول وتضمين مَعلمة طلب البحث scope، على النحو التالي:

curl -i -X POST -H content-type:application/x-www-form-urlencoded 'http://myorg-test.apigee.net/oauth/token?grant_type=client_credentials&scope=A X'

في هذه الحالة، سيتم منح الرمز المميّز الذي تم إنشاؤه النطاقَين A وX، لأنّ كلاً من A وX نطاق صالح. يُرجى العِلم أنّ تطبيق المطوّر يتعرّف على النطاقات A وB وC وX. في هذه الحالة، أنت تفلتر قائمة منتجات واجهة برمجة التطبيقات استنادًا إلى هذه النطاقات. إذا كان المنتج يتضمّن النطاق A أو X، يمكنك ضبط نقاط نهاية واجهة برمجة التطبيقات التي ستفرض هذه النطاقات. إذا لم يكن المنتج يتضمّن النطاق A أو X (على سبيل المثال، يتضمّن النطاقات B وC وZ)، لا يمكن طلب البيانات من واجهات برمجة التطبيقات التي تفرض النطاقين A أو X باستخدام الرمز المميز.

عند استدعاء واجهة برمجة التطبيقات باستخدام الرمز المميز الجديد، سيحدث ما يلي:

curl -X GET -H Authorization: Bearer Rkmqo2UkEIyIBCrtro1QpIG http://wwitman-test.apigee.net/scopecheck1/resourceX

يتم التحقّق من صحة رمز الدخول من خلال خادم وكيل لواجهة برمجة التطبيقات. على سبيل المثال:

<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthV2-VerifyAccessTokenX">
    <DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>VerifyAccessToken</Operation>
    <Scope>A X</Scope>
    <GenerateResponse enabled="true"/>
</OAuthV2>

يتم تشغيل طلب GET بنجاح ويتم عرض ردّ. على سبيل المثال:

 {
   "hello" : "Tue, 25 Nov 2014 01:35:53 UTC"
 }
 

تنجح العملية لأنّ سياسة VerifyAccessToken تتطلّب النطاق A أو X، ويتضمّن رمز الدخول النطاقَين A وX. بالطبع، إذا تم ضبط العنصر <Scope> على "B"، سيتعذّر تنفيذ هذا الطلب.

ملخّص

من المهم فهم طريقة تعامل Apigee Edge مع نطاقات OAuth 2.0. في ما يلي النقاط الرئيسية التي يجب تذكُّرها:

  • "يتعرّف" تطبيق المطوّر على اتحاد جميع النطاقات المحدّدة لجميع منتجاته.
  • عندما يطلب تطبيق رمز دخول، يمكنه تحديد النطاقات التي يريد الحصول عليها. يقع على عاتق Apigee Edge (خادم التفويض) تحديد النطاقات التي سيتم تعيينها لرمز الدخول استنادًا إلى (أ) النطاقات المطلوبة و(ب) النطاقات التي يتعرّف عليها تطبيق المطوّر.
  • إذا لم يتم ضبط Apigee Edge للتحقّق من النطاق (العنصر <Scope> غير متوفّر في سياسة VerifyAccessToken أو أنّه فارغ)، سينجح طلب البيانات من واجهة برمجة التطبيقات طالما أنّ النطاق المضمّن في رمز الدخول يطابق أحد النطاقات التي يتعرّف عليها تطبيق المطوّر المسجّل (أحد النطاقات في القائمة "الرئيسية" لنطاقات التطبيق).
  • إذا لم يكن رمز الدخول يتضمّن أي نطاقات مرتبطة به، لن ينجح إلا في الحالات التي لا يأخذ فيها Edge النطاق في الاعتبار (أي عندما يكون العنصر <Scope> غير متوفّر في سياسة VerifyAccessToken أو يكون فارغًا).