使用 OAuth2 範圍

本頁內容適用於 ApigeeApigee Hybrid

查看 Apigee Edge 說明文件。

本主題將討論如何透過 Apigee 使用及強制執行 OAuth 2.0 範圍。

什麼是 OAuth2 範圍?

OAuth 2.0 範圍可限制授予存取權杖的存取權量。舉例來說,核發給用戶端應用程式的存取權杖可能具有受保護資源的讀取和寫入權限,或只有讀取權限。您可以實作 API,強制執行任何範圍或範圍組合。因此,如果用戶端收到具有 READ 範圍的權杖,並嘗試呼叫需要 WRITE 存取權的 API 端點,呼叫就會失敗。

本主題將說明如何將範圍指派給存取權杖,以及 Apigee 如何強制執行 OAuth 2.0 範圍。閱讀本主題後,您就能自信地使用範圍。

如何將範圍指派給存取權杖?

Apigee 產生存取權杖時,可能會為該權杖指派範圍。如要瞭解發生這種情況的原因,您必須先熟悉下列 Apigee 實體:API 產品、開發人員和開發人員應用程式。如需簡介,請參閱「發布簡介」。建議您先詳閱這份資料,再繼續操作。

存取權杖是一長串隨機字元,可讓 Apigee 驗證傳入的 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"
}

權杖的中繼資料包括實際存取權杖字串、有效期限資訊、開發人員應用程式的識別資訊,以及與權杖相關聯的開發人員和產品。您也會發現中繼資料也包含「範圍」。

權杖如何取得範圍?

瞭解範圍的第一個關鍵,就是記住開發人員應用程式中的每個產品都可以指派零個或多個範圍。您可以在建立產品時指派這些範圍,也可以稍後再新增。這些名稱會以清單形式存在,並納入與各產品相關聯的「中繼資料」。

建立開發人員應用程式並新增產品後,Apigee 會查看開發人員應用程式中的所有產品,並建立這些產品的所有範圍清單 (應用程式的主範圍或全域範圍清單,也就是所有已識別範圍的聯集)。

用戶端應用程式向 Apigee 要求存取權杖時,可以選擇指定要與該權杖建立關聯的範圍。舉例來說,下列要求會要求「A」範圍。也就是說,用戶端要求授權伺服器 (Apigee) 產生具有「A」範圍的存取權杖 (授權應用程式呼叫具有「A」範圍的 API)。應用程式會傳送類似這樣的 POST 要求:

curl -i -X POST -H Authorization: Basic Mg12YTk2UkEIyIBCrtro1QpIG \
  -H content-type:application/x-www-form-urlencoded \
  https://apitest.acme.com/oauth/token?grant_type=client_credentials&scope=A

會發生什麼情況?

Apigee 收到這項要求時,會知道是哪個應用程式提出要求,以及用戶端註冊的開發人員應用程式 (用戶端 ID 和用戶端密碼金鑰會編碼在基本驗證標頭中)。由於包含 scope 查詢參數,Apigee 必須判斷與開發人員應用程式相關聯的 API 產品是否具有「A」範圍。如果符合,系統就會產生範圍為「A」的存取權杖。換句話說,範圍查詢參數是一種篩選器。如果開發人員應用程式可辨識「A、B、X」範圍,且查詢參數指定「scope=X Y Z」,則只有「X」範圍會指派給權杖。

如果用戶端未附加範圍參數,該怎麼辦?在這種情況下,Apigee 會產生權杖,其中包含開發人員應用程式可辨識的所有範圍。請務必瞭解,預設行為是傳回存取權杖,其中包含開發人員應用程式中所有產品的所有範圍聯集。

如果與開發人員應用程式相關聯的產品皆未指定範圍,且權杖確實有範圍,則使用該權杖發出的呼叫會失敗。

假設開發人員應用程式可辨識下列範圍:A B C D。這是應用程式的範圍主清單。應用程式中的一項產品可能具有範圍 A 和 B,另一項產品則具有範圍 C 和 D,或任何組合。如果用戶端未指定 scope 參數 (或指定沒有值的範圍參數),系統會授予權杖所有四個範圍:A、B、C 和 D。同樣地,權杖會收到一組範圍,這是開發人員應用程式可辨識的所有範圍的聯集。

如果 GenerateAccessToken 政策 (產生存取權杖的 Apigee 政策) 指定 <Scope> 元素,預設行為也會是傳回具有所有已識別範圍的存取權杖。舉例來說,以下是指定 <Scope> 的 GenerateAccessToken 政策。如果缺少 <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 中,存取權杖會透過 OAuthV2 政策 (通常放在 Proxy 流程的開頭) 進行驗證。政策必須指定 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 \
  https://apitest.acme.com/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 \
  https://apitest.acme.com/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 \
  'https://apitest.acme.com/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),則無法使用權杖呼叫強制執行範圍 A 或 X 的 API。

使用新權杖呼叫 API 時:

curl -X GET -H Authorization: Bearer Rkmqo2UkEIyIBCrtro1QpIG \
  https://apitest.acme.com/scopecheck1/resourceX

API Proxy 會驗證存取權杖。例如:

<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 如何處理 OAuth 2.0 範圍。以下是重點:

  • 開發人員應用程式會「辨識」為所有產品定義的所有範圍的聯集。
  • 應用程式要求存取權杖時,可以指定要取得哪些範圍的權限。Apigee (授權伺服器) 會根據 (a) 要求的一或多個範圍,以及 (b) 開發人員應用程式可辨識的範圍,決定實際要指派給存取權杖的範圍。
  • 如果 Apigee 未設定檢查範圍 (VerifyAccessToken 政策缺少 <Scope> 元素或該元素為空白),只要存取權權杖內嵌的範圍與註冊開發人員應用程式可辨識的範圍相符 (應用程式「主要」範圍清單中的其中一個範圍),API 呼叫就會成功。
  • 如果存取權杖沒有任何相關聯的範圍,只有在 Apigee 不考慮範圍時 (VerifyAccessToken 政策缺少 <Scope> 元素或該元素為空白),存取權杖才會成功。