Alibaba Cloud API Gateway menggunakan JSON Web Token (JWT) untuk mengotorisasi akses API berdasarkan sistem pengguna Anda, memungkinkan penerapan langkah-langkah keamanan kustom.
1. Autentikasi berbasis token
Ikhtisar
Banyak API publik perlu mengidentifikasi pemanggil untuk menentukan apakah akan memberikan akses ke resource yang diminta. Token merupakan mekanisme yang digunakan untuk verifikasi identitas. Dengan menggunakan token, aplikasi tidak perlu menyimpan informasi autentikasi atau sesi pengguna di server, sehingga memungkinkan otorisasi aplikasi web terdistribusi yang tanpa status dan menyederhanakan skalabilitas aplikasi.
Alur kerja
Gambar di atas menunjukkan alur kerja autentikasi Plugin JWT API Gateway, yang dijelaskan dalam langkah-langkah berikut:
Sebuah client mengirim permintaan yang berisi token ke API Gateway.
API Gateway menggunakan kunci publik yang dikonfigurasi di Plugin JWT untuk memverifikasi token dalam permintaan tersebut. Jika token valid, API Gateway meneruskan permintaan ke layanan backend.
Layanan backend memproses permintaan dan mengembalikan respons.
API Gateway mengembalikan respons dari layanan backend ke client.
Selama proses ini, API Gateway menggunakan mekanisme autentikasi token untuk mengotorisasi akses API berdasarkan sistem pengguna Anda. Bagian berikut menjelaskan JWT, yaitu token terstruktur yang digunakan API Gateway untuk autentikasi.
JWT
1.1 Ikhtisar
JWT adalah standar terbuka berbasis JSON (RFC 7519) untuk mentransmisikan klaim secara aman antar pihak dalam lingkungan aplikasi web. JWT dapat berfungsi sebagai token autentikasi mandiri, mencakup informasi seperti identitas pengguna, peran pengguna, dan izin yang memungkinkan client mengakses resource dari server resource. JWT juga dapat berisi klaim tambahan yang diperlukan oleh logika bisnis, sehingga sangat ideal untuk skenario login di situs terdistribusi.
1.2 Komposisi JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQSeperti yang ditunjukkan pada contoh di atas, JWT adalah string yang terdiri dari tiga bagian:
Header
Payload
Signature
Header
Header berisi dua informasi:
Jenis token, yaitu JWT.
Algoritma enkripsi yang digunakan.
Header lengkap berupa objek JSON, seperti pada contoh berikut:
{
'typ': 'JWT',
'alg': 'HS256'
}Header tersebut kemudian di-encode dengan Base64url untuk membentuk bagian pertama JWT.
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9Payload
Payload berisi informasi yang berguna. Rinciannya sebagai berikut:
iss: Penerbit token. Klaim ini berupa string yang menunjukkan siapa yang membuat token.
sub: Subject Identifier. Pengidentifikasi end user, yang disediakan oleh penerbit. Nilai ini unik dalam cakupan penerbit, case-sensitive, dan memiliki panjang maksimum 255 karakter ASCII.
aud: Audience(s). Penerima yang dituju oleh token. Ini adalah array string yang case-sensitive.
exp: Waktu kedaluwarsa. Timestamp saat token kedaluwarsa. Token menjadi tidak valid setelah waktu ini. Klaim ini berupa bilangan bulat yang merepresentasikan jumlah detik sejak 1970-01-01T00:00:00Z.
iat: Issued at. Waktu penerbitan token. Klaim ini berupa bilangan bulat yang merepresentasikan jumlah detik sejak 1970-01-01T00:00:00Z.
jti: JWT ID. Pengidentifikasi unik untuk token. Nilai klaim ini unik untuk setiap token yang dibuat oleh penerbit. Untuk mencegah konflik, biasanya berupa nilai acak kriptografis. Nilai ini menambahkan komponen entropi acak pada token terstruktur yang tidak dapat diperoleh penyerang, sehingga membantu mencegah serangan tebakan dan replay token.Anda juga dapat menambahkan klaim kustom yang dibutuhkan sistem pengguna Anda. Misalnya, Anda dapat menambahkan klaim name untuk nama panggilan pengguna, seperti pada kode berikut:
{
"sub": "1234567890",
"name": "John Doe"
}Payload tersebut kemudian di-encode dengan Base64url untuk membentuk bagian kedua JWT:
JTdCJTBBJTIwJTIwJTIyc3ViJTIyJTNBJTIwJTIyMTIzNDU2Nzg5MCUyMiUyQyUwQSUyMCUyMCUyMm5hbWUlMjIlM0ElMjAlMjJKb2huJTIwRG9lJTIyJTBBJTdESignature
Untuk membuat signature, gabungkan header yang telah di-encode Base64 dan payload yang telah di-encode Base64 dengan titik (.). Kemudian, tandatangani string hasil gabungan tersebut dengan algoritma yang ditentukan dalam header menggunakan kunci privat yang direpresentasikan oleh $secret. Signature ini membentuk bagian ketiga JWT.
// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, '$secret');Gabungkan ketiga bagian ini dengan titik (.) untuk membentuk string JWT lengkap, seperti yang ditunjukkan pada contoh JWT di awal bagian ini.
1.3 Cakupan otorisasi dan periode validitas
API Gateway memberikan akses token ke semua API yang terikat pada Plugin JWT dalam grup API yang sama. Untuk pengelolaan izin yang lebih granular, layanan backend Anda harus mengurai token dan melakukan pemeriksaan izin sendiri. API Gateway memvalidasi klaim `exp` dalam token. Jika token kedaluwarsa, API Gateway menganggapnya tidak valid dan menolak permintaan tersebut. Anda harus menetapkan waktu kedaluwarsa, dan periode validitas harus kurang dari tujuh hari.
1.4 Karakteristik JWT
Secara default, JWT tidak dienkripsi. Jangan sertakan data sensitif dalam JWT.
JWT dapat digunakan untuk autentikasi dan pertukaran informasi. Penggunaan JWT yang efektif dapat mengurangi jumlah kueri database di server. Kerugian utama JWT adalah sifatnya yang tanpa status. Artinya, Anda tidak dapat mencabut token atau mengubah izinnya sebelum masa berlakunya habis. Setelah JWT diterbitkan, token tersebut tetap valid hingga kedaluwarsa, kecuali server menerapkan logika tambahan untuk menangani pencabutan.
JWT berisi informasi autentikasi. Jika bocor, siapa pun dapat memperoleh semua izin yang terkait dengan token tersebut. Untuk mengurangi risiko ini, tetapkan periode validitas JWT yang singkat. Untuk tindakan yang memerlukan tingkat keamanan tinggi, lakukan autentikasi ulang terhadap pengguna sebelum memberikan akses.
Untuk mengurangi risiko pencurian, jangan transmisikan JWT dalam teks biasa melalui HTTP. Gunakan HTTPS sebagai gantinya.
2. Cara menggunakan Plugin JWT untuk melindungi API
2.1 Hasilkan pasangan JWK
2.1.1 Generasi online
Anda dapat mengunjungi https://tools.top/jwt-encode.html untuk menghasilkan kunci privat dan kunci publik guna pembuatan dan verifikasi token. Kunci privat digunakan oleh layanan otorisasi untuk menerbitkan JSON Web Keys (JWK). Kunci publik dikonfigurasi di Plugin JWT agar API Gateway dapat memverifikasi signature permintaan. API Gateway mendukung algoritma RSA SHA256 dan ukuran kunci 2048 bit untuk pasangan kunci.
2.1.2 Generasi lokal
Bagian ini memberikan contoh dalam Java. Anda dapat menemukan tool serupa dalam bahasa pemrograman lain untuk menghasilkan pasangan kunci. Pertama, buat proyek Maven dan tambahkan dependensi berikut:
<dependency>
<groupId>org.bitbucket.b_c</groupId>
<artifactId>jose4j</artifactId>
<version>0.7.0</version>
</dependency>Gunakan kode berikut untuk menghasilkan pasangan kunci RSA:
RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
rsaJsonWebKey.setKeyId("authServer");
final String publicKeyString = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.PUBLIC_ONLY);
final String privateKeyString = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE);2.2 Gunakan kunci privat dalam JWK untuk mengimplementasikan layanan penerbitan token
Gunakan string JSON kunci privat JWK yang dihasilkan secara online atau string JSON privateKeyString yang dihasilkan secara lokal di Bagian 2.1 sebagai kunci privat untuk menerbitkan token. Token ini mengotorisasi pengguna tepercaya untuk mengakses API yang dilindungi. Untuk informasi selengkapnya, lihat Contoh kode untuk layanan penerbitan token. Metode penerbitan token bergantung pada skenario bisnis Anda. Anda dapat men-deploy fitur penerbitan token ke lingkungan produksi dan mengonfigurasinya sebagai API standar. Pengguna kemudian dapat memperoleh token dengan memberikan username dan password. Atau, Anda dapat menghasilkan token di lingkungan lokal dan memberikannya langsung kepada pengguna tertentu.
2.3 Konfigurasikan kunci publik dari JWK di Plugin JWT
Masuk ke Konsol API Gateway.
Pada panel navigasi di sebelah kiri, pilih .
Pada halaman manajemen plug-in, klik Create Plug-in di pojok kanan atas.
Pada halaman Create Plug-in, atur Plug-in Name dan Plug-in Type. Kode berikut menunjukkan contoh konfigurasi untuk plug-in autentikasi JWT. Untuk informasi selengkapnya tentang konfigurasi, lihat Plug-in autentikasi JWT.
---
parameter: X-Token # Parameter tempat JWT diambil. Ini sesuai dengan parameter API.
parameterLocation: header # Lokasi pembacaan JWT. Parameter ini opsional jika mode permintaan API adalah mapping. Parameter ini wajib jika mode permintaan API adalah pass-through. Nilai yang valid: query dan header.
claimParameters: # Konversi parameter klaim. Gerbang memetakan klaim JWT ke parameter backend.
- claimName: aud # Nama klaim. Mendukung klaim publik dan privat.
parameterName: X-Aud # Nama parameter yang dipetakan.
location: header # Lokasi parameter yang dipetakan. Nilai yang valid: query, header, path, dan formData.
- claimName: userId # Nama klaim. Mendukung klaim publik dan privat.
parameterName: userId # Nama parameter yang dipetakan.
location: query # Lokasi parameter yang dipetakan. Nilai yang valid: query, header, path, dan formData.
preventJtiReplay: false # Menentukan apakah akan mengaktifkan pemeriksaan anti-replay untuk jti. Nilai default: false.
#
# Kunci publik JSON Web Key (JWK), yaitu bagian kunci publik yang dihasilkan di Bagian 2.1.
jwk:
kty: RSA
e: AQAB
use: sig
kid: uniq_key
alg: RS256
n: qSVxcknOm0uCq5vGsOmaorPDzHUubBmZZ4UXj-9do7w9X1uKFXAnqfto4TepSNuYU2bA_-tzSLAGBsR-BqvT6w9SjxakeiyQpVmexxnDw5WZwpWenUAcYrfSPEoNU-0hAQwFYgqZwJQMN8ptxkd0170PFauwACOx4Hfr-9FPGy8NCoIO4MfLXzJ3mJ7xqgIZp3NIOGXz-GIAbCf13ii7kSStpYqN3L_zzpvXUAos1FJ9IPXRV84tIZpFVh2lmRh0h8ImK-vI42dwlD_hOIzayL1Xno2R0T-d5AwTSdnep7g-Fwu8-sj4cCRWq3bd61Zs2QOJ8iustH0vSRMYdP5oYQ2.4 Ikat Plugin JWT ke API
Pada halaman Manajemen Plug-in, temukan plug-in autentikasi JWT yang telah Anda buat dan klik Bind API. Pada kotak dialog yang muncul, pilih API dari grup dan lingkungan yang ditentukan, tambahkan ke daftar di sebelah kanan, lalu klik OK.

Fitur debugging API di Konsol API Gateway tidak mendukung Plugin JWT. Untuk menguji API yang terikat pada Plugin JWT, Anda dapat menggunakan tool seperti Postman atau menjalankan perintah curl.
3. Contoh kode untuk layanan penerbitan token
import java.security.PrivateKey;
import org.jose4j.json.JsonUtil;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jwk.RsaJwkGenerator;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.NumericDate;
import org.jose4j.lang.JoseException;
public class GenerateJwtDemo {
public static void main(String[] args) throws JoseException {
// Gunakan keyId yang ditetapkan di API Gateway.
String keyId = "uniq_key";
// Gunakan pasangan kunci yang dihasilkan di Bagian 2.1.
String privateKeyJson = "{\n"
+ " \"kty\": \"RSA\",\n"
+ " \"d\": "
+
"\"O9MJSOgcjjiVMNJ4jmBAh0mRHF_TlaVva70Imghtlgwxl8BLfcf1S8ueN1PD7xV6Cnq8YenSKsfiNOhC6yZ_fjW1syn5raWfj68eR7cjHWjLOvKjwVY33GBPNOvspNhVAFzeqfWneRTBbga53Agb6jjN0SUcZdJgnelzz5JNdOGaLzhacjH6YPJKpbuzCQYPkWtoZHDqWTzCSb4mJ3n0NRTsWy7Pm8LwG_Fd3pACl7JIY38IanPQDLoighFfo-Lriv5z3IdlhwbPnx0tk9sBwQBTRdZ8JkqqYkxUiB06phwr7mAnKEpQJ6HvhZBQ1cCnYZ_nIlrX9-I7qomrlE1UoQ\",\n"
+ " \"e\": \"AQAB\",\n"
+ " \"kid\": \"myJwtKey\",\n"
+ " \"alg\": \"RS256\",\n"
+ " \"n\": \"vCuB8MgwPZfziMSytEbBoOEwxsG7XI3MaVMoocziP4SjzU4IuWuE_DodbOHQwb_thUru57_Efe"
+
"--sfATHEa0Odv5ny3QbByqsvjyeHk6ZE4mSAV9BsHYa6GWAgEZtnDceeeDc0y76utXK2XHhC1Pysi2KG8KAzqDa099Yh7s31AyoueoMnrYTmWfEyDsQL_OAIiwgXakkS5U8QyXmWicCwXntDzkIMh8MjfPskesyli0XQD1AmCXVV3h2Opm1Amx0ggSOOiINUR5YRD6mKo49_cN-nrJWjtwSouqDdxHYP-4c7epuTcdS6kQHiQERBd1ejdpAxV4c0t0FHF7MOy9kw\"\n"
+ "}";
JwtClaims claims = new JwtClaims();
claims.setGeneratedJwtId();
claims.setIssuedAtToNow();
// Waktu kedaluwarsa harus ditetapkan dan kurang dari 7 hari.
NumericDate date = NumericDate.now();
date.addSeconds(120*60);
claims.setExpirationTime(date);
claims.setNotBeforeMinutesInThePast(1);
claims.setSubject("YOUR_SUBJECT");
claims.setAudience("YOUR_AUDIENCE");
// Tambahkan parameter kustom. Semua nilai harus bertipe String.
claims.setClaim("userId", "1213234");
claims.setClaim("email", "userEm***@youapp.com");
JsonWebSignature jws = new JsonWebSignature();
jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
// Parameter ini wajib.
jws.setKeyIdHeaderValue(keyId);
jws.setPayload(claims.toJson());
PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyJson)).getPrivateKey();
jws.setKey(privateKey);
String jwtResult = jws.getCompactSerialization();
System.out.println("Generate Json Web token , result is " + jwtResult);
}
}Perhatikan poin-poin berikut mengenai contoh di atas:
keyIdharus bersifat unik secara global dan konsisten di lokasi-lokasi berikut:
keyIdyang Anda tentukan saat menghasilkan kunci di bagian Hasilkan pasangan JSON Web Key (JWK).kidyang Anda konfigurasikan di bagian Konfigurasikan kunci publik dari JWK di Plugin JWT.keyIddalam kode, yaitu nilai propertiKeyIdHeaderValuedari objekJsonWebSignature. Properti ini wajib.
Parameter privateKeyJson adalah string JSON JWK dari kunci publik yang dihasilkan secara online, sebagaimana dijelaskan dalam Bagian 2.1, atau secara lokal.
String JSON
privateKeyString.Periode validitas diperlukan dan harus kurang dari tujuh hari.
Gunakan nilai bertipe String untuk semua parameter kustom.
4. Tanggapan kesalahan API Gateway
Status | Kode | Pesan | Deskripsi |
400 | I400JR | JWT diperlukan | Parameter JWT tidak ditemukan. |
403 | S403JI | Klaim jti diperlukan saat preventJtiReplay:true | Permintaan tidak menyediakan jti yang valid saat fitur anti-replay diaktifkan di plug-in autentikasi JWT. |
403 | S403JU | Klaim jti dalam JWT digunakan | jti yang disediakan dalam permintaan telah digunakan saat fitur anti-replay diaktifkan di plug-in autentikasi JWT. |
403 | A403JT | JWT tidak valid: ${Reason} | JWT yang disediakan dalam permintaan tidak valid. |
400 | I400JD | JWT Deserialize Gagal: ${Token} | Gagal mengurai JWT yang disediakan dalam permintaan. |
403 | A403JK | Tidak ada JWK yang cocok, kid:${kid} tidak ditemukan | kid dalam JWT permintaan tidak cocok dengan JWK mana pun. |
403 | A403JE | JWT kedaluwarsa pada ${Date} | JWT yang disediakan dalam permintaan telah kedaluwarsa. |
400 | I400JP | Konfigurasi plugin JWT tidak valid: ${JWT} | Konfigurasi plug-in autentikasi JWT salah. |
Jika Anda menerima kode status yang tidak terduga, periksa header X-Ca-Error-Code dalam respons HTTP untuk mendapatkan ErrorCode dan header X-Ca-Error-Message untuk mendapatkan ErrorMessage. Jika kode kesalahan adalah A403JT atau I400JD, Anda dapat menggunakan situs web jwt.io untuk memeriksa validitas dan format token Anda.