کار با محدوده‌های OAuth2

درحال مشاهده اسناد Apigee Edge هستید.
به اسناد Apigee X بروید.
اطلاعات

این موضوع درباره نحوه استفاده از محدوده‌های OAuth 2.0 در Apigee Edge بحث می‌کند.

محدوده OAuth2 چیست؟

محدوده‌های OAuth 2.0 روشی برای محدود کردن میزان دسترسی اعطاشده به کد دسترسی ارائه می‌دهند. برای مثال، کد دسترسی صادرشده برای برنامه مشتری ممکن است دسترسی «خواندن» و «نوشتن» به منابع محافظت‌شده یا فقط دسترسی «خواندن» را اعطا کند. می‌توانید میاناهای برنامه‌سازی کاربردی خود را برای اعمال هر حوزه یا ترکیبی از حوزه‌های موردنظرتان پیاده‌سازی کنید. بنابراین، اگر کارخواهی نشانه‌ای دریافت کند که محدوده READ دارد و تلاش کند نقطه پایانی «میانای برنامه‌سازی کاربردی» را فراخوانی کند که به دسترسی WRITE نیاز دارد، فراخوانی ناموفق خواهد بود.

در این موضوع، درباره نحوه اختصاص دامنه‌ها به کد دسترسی و نحوه اعمال دامنه‌های OAuth 2.0 توسط Apigee Edge بحث خواهیم کرد. پس‌از خواندن این موضوع، می‌توانید با اطمینان از محدوده‌ها استفاده کنید.

حوزه‌ها چگونه به کدهای دسترسی اختصاص داده می‌شوند؟

وقتی Edge کد دسترسی تولید می‌کند، ممکن است دامنه‌ای را به آن کد اختصاص دهد. برای درک نحوه وقوع این اتفاق، ابتدا باید با این نهادهای Apigee Edge آشنا باشید: محصولات API، توسعه‌دهندگان، و برنامه‌های توسعه‌دهنده. برای آشنایی، مقدمه‌ای بر انتشار را ببینید. توصیه می‌کنیم که درصورت نیاز، قبل‌از ادامه دادن این مطالب را مرور کنید.

کد دسترسی رشته‌ای طولانی از نویسه‌های به‌ظاهر تصادفی است که به Edge اجازه می‌دهد درخواست‌های ورودی API را درستی‌سنجی کند (آن را جایگزینی برای اطلاعات اعتباری نام کاربری/گذرواژه معمولی درنظر بگیرید). ازنظر فنی، این نشان کلیدی است که به مجموعه‌ای از فراداده‌ها اشاره می‌کند که به این شکل است:

{
  "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) یک کد دسترسی با حوزه «A» تولید کند (به برنامه اجازه می‌دهد تا میاناهای برنامه‌سازی کاربردی با حوزه «A» را فراخوانی کند). برنامه درخواست 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 باید تصمیم بگیرد که آیا هیچ‌یک از محصولات API مرتبط با برنامه توسعه‌دهنده دارای محدوده «الف» هستند یا نه. اگر این کار را انجام دهد، یک کد دسترسی با محدوده «A» تولید می‌شود. روش دیگر برای نگاه کردن به این موضوع این است که پارامتر پرسش دامنه نوعی فیلتر است. اگر برنامه توسعه‌دهنده دامنه‌های «A،‏ B،‏ X» را تشخیص دهد و پارامتر پُرسمان «scope=X Y Z» را مشخص کند، فقط دامنه «X» به رمز اختصاص داده خواهد شد.

اگر کارخواه پارامتر محدوده را پیوست نکند چه می‌شود؟ در این مورد، Edge نشانه‌ای تولید می‌کند که شامل همه محدوده‌هایی است که برنامه توسعه‌دهنده تشخیص می‌دهد. مهم است بدانید که رفتار پیش‌فرض این است که یک کد دسترسی برگرداند که شامل اتحاد همه محدوده‌ها برای همه محصولات موجود در برنامه توسعه‌دهنده است.

اگر هیچ‌یک از محصولات منسوب به برنامه توسعه‌دهنده دامنه‌ها را مشخص نکرده باشند و رمز دارای دامنه باشد، فراخوانی‌های انجام‌شده با آن رمز ناموفق خواهد بود.

فرض کنیم برنامه توسعه‌دهنده‌ای این محدوده‌ها را تشخیص می‌دهد: A B C D. این فهرست اصلی برنامه از حوزه‌ها است. ممکن است یک محصول در برنامه دارای حوزه 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> را یادداشت کنید. از آن برای مشخص کردن اینکه خط‌مشی کدام محدوده‌ها را می‌پذیرد استفاده می‌شود.

در این مثال، خط‌مشی فقط درصورتی موفق خواهد بود که کد دسترسی شامل حوزه «A» باشد. اگر این عنصر <Scope> حذف شود یا مقدار نداشته باشد، خط‌مشی حوزه توکن دسترسی را نادیده می‌گیرد.

اکنون با قابلیت اعتبارسنجی کدهای دسترسی براساس محدوده، می‌توانید میاناهای برنامه‌سازی کاربردی خود را به‌گونه‌ای طراحی کنید که محدوده‌های خاصی را اعمال کند. این کار را با طراحی جریان‌های سفارشی با خط‌مشی‌های VerifyAccessToken آگاه از محدوده که به آن‌ها پیوست شده است انجام می‌دهید.

فرض کنیم API شما جریانی برای نقطه پایانی /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>

به‌طور خلاصه، توسعه‌دهندگان API مسئول طراحی اجرای محدوده در APIهای خود هستند. آن‌ها این کار را با ایجاد جریان‌های سفارشی برای مدیریت دامنه‌های خاص و پیوست کردن خط‌مشی‌های VerifyAccessToken برای اعمال آن دامنه‌ها انجام می‌دهند.

نمونه‌های کد

در نهایت، بیایید نگاهی به چند نمونه فراخوانی API بیندازیم تا نحوه دریافت محدوده‌ها توسط نشان‌ها و نحوه اعمال محدوده‌ها را نشان دهیم.

حالت پیش‌فرض

فرض کنیم برنامه توسعه‌دهنده‌ای با محصولات دارید و اجتماع حوزه‌های آن محصولات عبارت‌اند از: A،‏ B، و C. این فراخوانی API یک کد دسترسی درخواست می‌کند، اما پارامتر پُرسمان محدوده را مشخص نمی‌کند.

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"
}

اکنون، فرض کنیم نقطه پایانی API دارید که محدوده «الف» دارد (یعنی 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 را اعمال می‌کنند با کد فراخوانی کرد.

وقتی API را با کد جدید فراخوانی می‌کنید:

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

کد دسترسی توسط پراکسی API اعتبارسنجی می‌شود. برای مثال:

<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> روی «ب» تنظیم شده باشد، این تماس ناموفق خواهد بود.

خلاصه

مهم است که بدانید Apigee Edge چگونه دامنه‌های OAuth 2.0 را مدیریت می‌کند. در اینجا نکات کلیدی آورده شده است:

  • برنامه توسعه‌دهنده اتحاد همه محدوده‌های تعریف‌شده برای همه محصولاتش را «تشخیص می‌دهد».
  • وقتی برنامه‌ای درخواست کد دسترسی می‌کند، این فرصت را دارد که مشخص کند کدام محدوده‌ها را می‌خواهد. این وظیفه Apigee Edge (سرور مجوز) است که براساس (الف) دامنه‌هایی که درخواست شده است و (ب) دامنه‌هایی که برنامه توسعه‌دهنده تشخیص می‌دهد، تعیین کند که کدام دامنه‌ها را به کد دسترسی اختصاص دهد.
  • اگر Apigee Edge برای بررسی محدوده پیکربندی نشده باشد (عنصر <Scope> در خط‌مشی VerifyAccessToken وجود نداشته باشد یا خالی باشد)، تا زمانی که محدوده جاسازی‌شده در کد دسترسی با یکی از محدوده‌های شناخته‌شده توسط برنامه توسعه‌دهنده ثبت‌شده مطابقت داشته باشد (یکی از محدوده‌های موجود در فهرست «اصلی» محدوده‌های برنامه)، تماس با API موفق خواهد بود.
  • اگر یک کد دسترسی هیچ دامنه‌ای نداشته باشد، فقط در مواردی موفق خواهد بود که Edge دامنه را درنظر نگیرد (عنصر <Scope> در خط‌مشی VerifyAccessToken وجود نداشته باشد یا خالی باشد).