TL;DR
Scopes OAuth 2.0 adalah string izin yang menentukan apa yang dapat dilakukan oleh token akses. Gunakan format resource:action seperti pets:read atau orders:write. Minta scopes selama otorisasi, validasi di endpoint API. Modern PetstoreAPI mengimplementasikan scopes untuk akses baca/tulis ke hewan peliharaan, pesanan, dan data pengguna.
Pendahuluan
Sebuah aplikasi pihak ketiga ingin membaca inventaris toko hewan peliharaan Anda. Haruskah aplikasi tersebut memiliki akses penuh untuk membuat pesanan, menghapus hewan peliharaan, dan mengelola pengguna? Tidak. Aplikasi tersebut seharusnya hanya membaca inventaris.
Scopes OAuth 2.0 menyelesaikan masalah ini. Scopes menentukan izin apa yang dimiliki oleh token akses. Aplikasi meminta scope inventory:read. API Anda memvalidasi token memiliki scope ini sebelum mengembalikan data.
Modern PetstoreAPI mengimplementasikan scopes granular untuk semua sumber daya: hewan peliharaan, pesanan, inventaris, dan pengguna.
Jika Anda menguji API OAuth, Apidog membantu Anda menguji validasi scope dan alur otorisasi.
Apa Itu Scopes OAuth 2.0?
Scopes adalah string izin yang disertakan dalam token akses OAuth.
Format Scope
pets:read - Baca data hewan peliharaan
pets:write - Buat/perbarui hewan peliharaan
orders:read - Baca pesanan
orders:write - Buat pesanan
admin:all - Akses admin penuh
Scope dalam Alur OAuth
1. Permintaan Otorisasi:
GET /oauth/authorize?
client_id=app123&
scope=pets:read orders:read&
redirect_uri=https://app.com/callback
2. Persetujuan Pengguna:
Aplikasi "PetFinder" ingin:
- Membaca hewan peliharaan Anda
- Membaca pesanan Anda
[Izinkan] [Tolak]
3. Token Akses:
{
"access_token": "eyJhbGc...",
"scope": "pets:read orders:read",
"expires_in": 3600
}
4. Permintaan API:
GET /v1/pets
Authorization: Bearer eyJhbGc...
200 OK (scope tervalidasi)
Bagaimana Scopes Bekerja
Token Berisi Scopes
Token akses mencakup scopes yang diberikan:
// JWT yang Didekode
{
"sub": "user-456",
"scope": "pets:read orders:read",
"exp": 1710331200
}
API Memvalidasi Scopes
app.get('/v1/pets', requireScope('pets:read'), async (req, res) => {
const pets = await getPets();
res.json(pets);
});
app.post('/v1/pets', requireScope('pets:write'), async (req, res) => {
const pet = await createPet(req.body);
res.status(201).json(pet);
});
function requireScope(requiredScope) {
return (req, res, next) => {
const token = extractToken(req);
const decoded = verifyToken(token);
if (!decoded.scope.includes(requiredScope)) {
return res.status(403).json({
error: 'insufficient_scope',
message: `Membutuhkan scope: ${requiredScope}`
});
}
next();
};
}
Mendesain Scopes
Konvensi Penamaan Scope
Pola Sumber Daya:Tindakan (Resource:Action):
pets:read
pets:write
orders:read
orders:write
users:read
users:write
Scopes Granular:
pets:read
pets:create
pets:update
pets:delete
Scopes Wildcard:
pets:* - Semua operasi hewan peliharaan
*:read - Baca semua sumber daya
admin:* - Akses admin penuh
Hierarki Scope
admin:all
├── pets:*
│ ├── pets:read
│ ├── pets:write
│ └── pets:delete
├── orders:*
│ ├── orders:read
│ └── orders:write
└── users:*
├── users:read
└── users:write
Mengimplementasikan Validasi Scope
Pendekatan Middleware
function requireScopes(...requiredScopes) {
return (req, res, next) => {
const token = extractToken(req);
const decoded = verifyToken(token);
const tokenScopes = decoded.scope.split(' ');
const hasAllScopes = requiredScopes.every(scope =>
tokenScopes.includes(scope) || tokenScopes.includes('admin:all')
);
if (!hasAllScopes) {
return res.status(403).json({
error: 'insufficient_scope',
required: requiredScopes,
provided: tokenScopes
});
}
req.user = decoded;
next();
};
}
// Penggunaan
app.get('/v1/pets', requireScopes('pets:read'), getPets);
app.post('/v1/pets', requireScopes('pets:write'), createPet);
app.delete('/v1/pets/:id', requireScopes('pets:delete'), deletePet);
Pendekatan Dekorator (TypeScript)
function RequireScopes(...scopes: string[]) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const req = args[0];
const res = args[1];
const token = extractToken(req);
const decoded = verifyToken(token);
if (!hasScopes(decoded.scope, scopes)) {
return res.status(403).json({ error: 'insufficient_scope' });
}
return originalMethod.apply(this, args);
};
};
}
// Penggunaan
class PetsController {
@RequireScopes('pets:read')
async getPets(req, res) {
const pets = await this.petService.findAll();
res.json(pets);
}
@RequireScopes('pets:write')
async createPet(req, res) {
const pet = await this.petService.create(req.body);
res.status(201).json(pet);
}
}
Bagaimana Modern PetstoreAPI Menggunakan Scopes
Scopes yang Tersedia
pets:read - Baca data hewan peliharaan
pets:write - Buat/perbarui hewan peliharaan
pets:delete - Hapus hewan peliharaan
orders:read - Baca pesanan
orders:write - Buat pesanan
inventory:read - Baca inventaris
inventory:write - Perbarui inventaris
users:read - Baca profil pengguna
users:write - Perbarui profil pengguna
admin:all - Akses penuh
Validasi Scope
GET /v1/pets
Authorization: Bearer token_dengan_pets:read
200 OK
POST /v1/pets
Authorization: Bearer token_dengan_pets:read
403 Terlarang
{
"error": "insufficient_scope",
"required": ["pets:write"],
"provided": ["pets:read"]
}
Lihat dokumentasi OAuth Modern PetstoreAPI.
Menguji Scopes dengan Apidog
Apidog mendukung pengujian scope OAuth:
- Konfigurasi otorisasi OAuth 2.0
- Minta scope tertentu
- Uji endpoint dengan scope yang berbeda
- Validasi respons 403 untuk scope yang tidak memadai
Praktik Terbaik
1. Gunakan scopes granular - pets:read bukan read_all
2. Ikuti konvensi penamaan - format resource:action
3. Dokumentasikan semua scopes - Cantumkan dalam dokumentasi API
4. Validasi pada setiap permintaan - Jangan percaya klien
5. Kembalikan pesan kesalahan yang jelas - Tunjukkan scopes yang diperlukan vs. yang disediakan
6. Gunakan hak istimewa paling rendah - Minta scopes minimum yang dibutuhkan
Kesimpulan
Scopes OAuth 2.0 menyediakan kontrol akses granular. Gunakan format resource:action, validasi pada setiap permintaan, dan dokumentasikan semua scopes. Modern PetstoreAPI menunjukkan implementasi scope yang siap produksi.
FAQ
Apa perbedaan antara scopes dan roles?
Scopes adalah izin untuk token akses. Roles adalah grup pengguna dengan izin yang ditetapkan.
Bisakah Anda memiliki beberapa scopes?
Ya, pisahkan dengan spasi: pets:read orders:read users:write
Bagaimana cara mencabut scopes?
Cabut token akses atau terbitkan token baru dengan scopes yang berbeda.
Haruskah scopes ada di JWT?
Ya, sertakan dalam klaim scope untuk validasi tanpa status.
Seberapa granular seharusnya scopes?
Seimbangkan granularitas dengan kegunaan. pets:read dan pets:write biasanya sudah cukup.
