کار با دامنه های OAuth2

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

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

دامنه OAuth2 چیست؟

دامنه‌های OAuth 2.0 راهی برای محدود کردن میزان دسترسی اعطا شده به یک access token ارائه می‌دهند. به عنوان مثال، یک access token که برای یک برنامه کلاینت صادر می‌شود، ممکن است دسترسی READ و WRITE به منابع محافظت شده یا فقط دسترسی READ را دریافت کند. شما می‌توانید API های خود را برای اعمال هر دامنه یا ترکیبی از دامنه‌های مورد نظر خود پیاده‌سازی کنید. بنابراین، اگر کلاینتی token ای را دریافت کند که دارای دامنه READ است و سعی کند یک API endpoint را که نیاز به دسترسی 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"
}

متادیتای توکن شامل رشته توکن دسترسی واقعی، اطلاعات انقضا، شناسایی برنامه توسعه‌دهنده، توسعه‌دهنده و محصولات مرتبط با توکن است. همچنین متوجه خواهید شد که متادیتا شامل «دامنه» نیز می‌شود.

توکن چگونه دامنه کاربرد خود را پیدا می‌کند؟

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

وقتی یک برنامه‌ی توسعه‌دهنده ایجاد می‌کنید و محصولاتی را به آن اضافه می‌کنید، اج تمام محصولات موجود در برنامه‌ی توسعه‌دهنده را بررسی می‌کند و فهرستی از تمام حوزه‌های (scope) آن محصولات ایجاد می‌کند (لیست اصلی یا سراسری حوزه‌های برنامه -- مجموعه‌ای از تمام حوزه‌های شناخته‌شده).

وقتی یک برنامه‌ی کلاینت از Apigee Edge درخواست یک توکن دسترسی می‌کند، می‌تواند به صورت اختیاری مشخص کند که می‌خواهد کدام حوزه‌ها را با آن توکن مرتبط کند. برای مثال، درخواست زیر حوزه "A" را درخواست می‌کند. یعنی کلاینت از سرور مجوز (Edge) می‌خواهد که یک توکن دسترسی با حوزه "A" ایجاد کند (به برنامه اجازه می‌دهد تا APIهایی را که حوزه "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" ایجاد می‌شود. روش دیگر برای بررسی این موضوع این است که پارامتر جستجوی محدوده نوعی فیلتر است. اگر برنامه توسعه‌دهنده محدوده‌های "A، B، X" را تشخیص دهد و پارامتر جستجو "scope=XYZ" را مشخص کند، فقط محدوده "X" به توکن اختصاص داده می‌شود.

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

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

فرض کنید یک برنامه‌ی توسعه‌دهنده این محدوده‌ها را تشخیص می‌دهد: ABC 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> حذف شود یا مقداری نداشته باشد، این سیاست محدوده توکن دسترسی را نادیده می‌گیرد.

اکنون، با قابلیت اعتبارسنجی توکن‌های دسترسی بر اساس دامنه، می‌توانید APIهای خود را برای اعمال دامنه‌های خاص طراحی کنید. شما این کار را با طراحی جریان‌های سفارشی با سیاست‌های 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 دارید که دامنه "A" دارد (یعنی VerifyAccessToken آن به دامنه "A" نیاز دارد). سیاست 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 را تشخیص می‌دهد. در این حالت، شما لیست محصولات API را بر اساس این دامنه‌ها فیلتر می‌کنید. اگر محصولی دامنه A یا X داشته باشد، می‌توانید نقاط پایانی API را پیکربندی کنید که این دامنه‌ها را اعمال کنند. اگر محصولی دامنه A یا X نداشته باشد (مثلاً B، C و Z داشته باشد)، APIهایی که دامنه‌های 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> روی "B" تنظیم شده باشد، این فراخوانی با شکست مواجه می‌شود.

خلاصه

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

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