Menggunakan cakupan OAuth2

Halaman ini berlaku untuk Apigee dan Apigee hybrid.

Lihat dokumentasi Apigee Edge.

Topik ini membahas cara menggunakan dan menerapkan cakupan OAuth 2.0 dengan Apigee.

Apa yang dimaksud dengan cakupan OAuth2?

Cakupan OAuth 2.0 menyediakan cara untuk membatasi jumlah akses yang diberikan ke token akses. Misalnya, token akses yang dikeluarkan untuk aplikasi klien dapat diberi akses BACA dan TULIS ke resource yang dilindungi, atau hanya akses BACA. Anda dapat menerapkan API untuk menerapkan cakupan atau kombinasi cakupan yang Anda inginkan. Jadi, jika klien menerima token yang memiliki cakupan BACA, dan mencoba memanggil endpoint API yang memerlukan akses MENULIS, panggilan akan gagal.

Dalam topik ini, kita akan membahas cara cakupan ditetapkan ke token akses dan cara Apigee menerapkan cakupan OAuth 2.0. Setelah membaca topik ini, Anda akan dapat menggunakan cakupan dengan percaya diri.

Bagaimana cakupan ditetapkan ke token akses?

Saat membuat token akses, Apigee dapat menetapkan cakupan ke token tersebut. Untuk memahami cara hal ini terjadi, Anda harus memahami entitas Apigee ini terlebih dahulu: produk API, developer, dan aplikasi developer. Untuk pengantar, lihat Pengantar publikasi. Sebaiknya tinjau materi ini jika perlu sebelum melanjutkan.

Token akses adalah string panjang karakter yang tampak acak yang memungkinkan Apigee memverifikasi permintaan API yang masuk (anggaplah sebagai pengganti kredensial nama pengguna/sandi biasa). Secara teknis, token adalah kunci yang merujuk ke kumpulan metadata yang terlihat seperti ini:

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

Metadata token mencakup string token akses yang sebenarnya, informasi masa berlaku, identifikasi aplikasi developer, developer, dan produk yang terkait dengan token. Anda juga akan melihat bahwa metadata juga menyertakan "cakupan".

Bagaimana token mendapatkan cakupannya?

Kunci pertama untuk memahami cakupan adalah mengingat bahwa setiap produk di aplikasi developer dapat memiliki nol atau beberapa cakupan yang ditetapkan. Cakupan ini dapat ditetapkan saat produk dibuat, atau dapat ditambahkan nanti. Nama tersebut ada sebagai daftar nama dan disertakan dalam "metadata" yang terkait dengan setiap produk.

Saat Anda membuat aplikasi developer dan menambahkan produk ke dalamnya, Apigee akan melihat semua produk di aplikasi developer dan membuat daftar semua cakupan untuk produk tersebut (daftar cakupan master atau global aplikasi -- gabungan dari semua cakupan yang dikenali).

Saat meminta token akses dari Apigee, aplikasi klien dapat menentukan cakupan mana yang ingin dikaitkan dengan token tersebut. Misalnya, permintaan berikut meminta cakupan "A". Artinya, klien meminta server otorisasi (Apigee) untuk membuat token akses yang memiliki cakupan "A" (memberi otorisasi aplikasi untuk memanggil API yang memiliki cakupan "A"). Aplikasi mengirim permintaan POST seperti ini:

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

Apa yang terjadi?

Saat menerima permintaan ini, Apigee mengetahui aplikasi mana yang membuat permintaan dan mengetahui aplikasi developer mana yang didaftarkan klien (ID klien dan kunci rahasia klien dienkode dalam header autentikasi dasar). Karena parameter kueri scope disertakan, Apigee perlu memutuskan apakah ada produk API yang terkait dengan aplikasi developer yang memiliki cakupan "A". Jika demikian, token akses akan dibuat dengan cakupan "A". Cara lain untuk melihat hal ini adalah parameter kueri cakupan adalah jenis filter. Jika aplikasi developer mengenali cakupan "A, B, X", dan parameter kueri menentukan "scope=X Y Z", maka hanya cakupan "X" yang akan ditetapkan ke token.

Bagaimana jika klien tidak melampirkan parameter cakupan? Dalam hal ini, Apigee menghasilkan token yang menyertakan semua cakupan yang dikenali oleh aplikasi developer. Penting untuk memahami bahwa perilaku default-nya adalah menampilkan token akses yang berisi gabungan semua cakupan untuk semua produk yang disertakan dalam aplikasi developer.

Jika tidak ada produk yang terkait dengan aplikasi developer yang menentukan cakupan, dan token memiliki cakupan, panggilan yang dilakukan dengan token tersebut akan gagal.

Misalkan aplikasi developer mengenali cakupan ini: A B C D. Ini adalah daftar master cakupan aplikasi. Mungkin satu produk di aplikasi memiliki cakupan A dan B, dan produk kedua memiliki cakupan C dan D, atau kombinasi apa pun. Jika klien tidak menentukan parameter scope (atau jika menentukan parameter cakupan tanpa nilai), token akan diberi keempat cakupan: A, B, C, dan D. Sekali lagi, token menerima kumpulan cakupan yang merupakan gabungan dari semua cakupan yang dikenali oleh aplikasi developer.

Ada satu kasus lagi saat perilaku defaultnya adalah menampilkan token akses dengan semua cakupan yang dikenali, dan itu terjadi saat kebijakan GenerateAccessToken (kebijakan Apigee yang menghasilkan token akses) tidak menentukan elemen <Scope>. Misalnya, berikut adalah kebijakan GenerateAccessToken dengan <Scope> ditentukan. Jika elemen <Scope> tersebut tidak ada (atau jika ada, tetapi kosong), perilaku default akan dijalankan.

<?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>

Bagaimana cakupan diterapkan?

Pertama, ingat bahwa di Apigee, token akses divalidasi dengan kebijakan OAuthV2 (biasanya ditempatkan di awal alur proxy). Kebijakan harus memiliki operasi VerifyAccessToken yang ditentukan. Mari kita lihat kebijakan ini:

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

Perhatikan elemen <Scope>. Ini digunakan untuk menentukan cakupan yang akan diterima kebijakan.

Dalam contoh ini, kebijakan hanya akan berhasil jika token akses menyertakan cakupan "A". Jika elemen <Scope> ini dihilangkan atau jika tidak memiliki nilai, kebijakan akan mengabaikan cakupan token akses.

Sekarang, dengan kemampuan untuk memvalidasi token akses berdasarkan cakupan, Anda dapat mendesain API untuk menerapkan cakupan tertentu. Anda melakukannya dengan mendesain alur kustom dengan kebijakan VerifyAccessToken yang berbasis cakupan yang terpasang padanya.

Misalnya, API Anda memiliki alur yang ditentukan untuk endpoint /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>

Saat alur ini dipicu (permintaan masuk dengan /resourceA di akhiran jalur), kebijakan OAuthV2-VerifyAccessTokenA akan segera dipanggil. Kebijakan ini memverifikasi bahwa token akses valid dan melihat cakupan yang didukung token. Jika kebijakan dikonfigurasi seperti contoh di bawah, dengan <Scope>A</Scope>, kebijakan hanya akan berhasil jika token akses memiliki cakupan "A". Jika tidak, sistem akan menampilkan error.

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

Singkatnya, developer API bertanggung jawab untuk mendesain penerapan cakupan ke dalam API mereka. Mereka melakukannya dengan membuat alur kustom untuk menangani cakupan tertentu, dan melampirkan kebijakan VerifyAccessToken untuk menerapkan cakupan tersebut.

Contoh kode

Terakhir, mari kita lihat beberapa contoh panggilan API untuk membantu mengilustrasikan cara token menerima cakupan dan cara cakupan diterapkan.

Kasus default

Misalkan Anda memiliki aplikasi developer dengan produk, dan gabungan cakupan produk tersebut adalah: A, B, dan C. Panggilan API ini meminta token akses, tetapi tidak menentukan parameter kueri cakupan.

curl -X POST -H content-type:application/x-www-form-urlencoded \
  https://apitest.acme.com/scopecheck1/token?grant_type=client_credentials

Dalam hal ini, token yang dihasilkan akan diberi cakupan A, B, dan C (perilaku default). Metadata token akan terlihat seperti ini:

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

Sekarang, misalkan Anda memiliki endpoint API yang memiliki cakupan "A" (yaitu, VerifyAccessToken memerlukan cakupan "A"). Berikut adalah kebijakan 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>

Berikut adalah contoh panggilan ke dan endpoint yang menerapkan cakupan A:

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

Panggilan GET ini berhasil:

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

Hal ini berhasil karena kebijakan VerifyAccessToken yang dipicu saat endpoint dipanggil memerlukan cakupan A, dan token akses diberi cakupan A, B, dan C -- perilaku default.

Memfilter kasus

Misalkan Anda memiliki aplikasi developer dengan produk yang memiliki cakupan A, B, C, dan X. Anda meminta token akses dan menyertakan parameter kueri scope, seperti ini:

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'

Dalam hal ini, token yang dihasilkan akan diberi cakupan A dan X, karena A dan X adalah cakupan yang valid. Ingat bahwa aplikasi developer mengenali cakupan A, B, C, dan X. Dalam hal ini, Anda memfilter daftar produk API berdasarkan cakupan ini. Jika produk memiliki cakupan A atau X, Anda dapat mengonfigurasi endpoint API yang akan menerapkan cakupan ini. Jika produk tidak memiliki cakupan A atau X (misalnya, memiliki B, C, dan Z), API yang menerapkan cakupan A atau X tidak dapat dipanggil dengan token.

Saat Anda memanggil API dengan token baru:

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

Token akses divalidasi oleh proxy API. Contoh:

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

Pemicu panggilan GET berhasil dan menampilkan respons. Contoh:

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

Tindakan ini berhasil karena kebijakan VerifyAccessToken memerlukan cakupan A atau X, dan token akses mencakup cakupan A dan X. Tentu saja, jika elemen <Scope> ditetapkan ke "B", panggilan ini akan gagal.

Ringkasan

Penting untuk memahami cara Apigee menangani cakupan OAuth 2.0. Berikut adalah poin-poin penting:

  • Aplikasi developer "mengenali" gabungan semua cakupan yang ditentukan untuk semua produknya.
  • Saat meminta token akses, aplikasi memiliki kesempatan untuk menentukan cakupan yang ingin dimiliki. Apigee (server otorisasi) dapat menentukan cakupan mana yang akan benar-benar ditetapkan ke token akses berdasarkan (a) cakupan yang diminta dan (b) yang dikenali oleh aplikasi developer.
  • Jika Apigee tidak dikonfigurasi untuk memeriksa cakupan (elemen <Scope> tidak ada dalam kebijakan VerifyAccessToken atau kosong), panggilan API akan berhasil selama cakupan yang disematkan dalam token akses cocok dengan salah satu cakupan yang dikenali oleh aplikasi developer terdaftar (salah satu cakupan dalam daftar cakupan "master" aplikasi).
  • Jika token akses tidak memiliki cakupan yang terkait dengannya, token tersebut hanya akan berhasil jika Apigee tidak mempertimbangkan cakupan (elemen <Scope> tidak ada dari kebijakan VerifyAccessToken atau kosong).