Wordpress REST API Custom Endpoints Nonces Permission Callbacks Auth Flow
Definisi singkat
WordPress REST API adalah lapisan HTTP JSON yang dipakai untuk membaca atau memodifikasi data WordPress tanpa harus melalui render halaman HTML. Di theme atau plugin work, REST API biasanya dipakai saat kamu butuh komunikasi yang lebih eksplisit antara browser, aplikasi lain, atau kode custom yang tidak cocok dijalankan lewat template biasa.
REST API WordPress bukan sekadar “endpoint JSON”. Di dalamnya ada alur penting: route harus diregister, request harus lolos permission check, callback baru boleh jalan, lalu respons dikembalikan dalam format yang konsisten.
Kapan pakai REST API
Pakai REST API kalau kebutuhanmu cocok dengan pola request/response yang jelas, misalnya:
- frontend JavaScript perlu mengambil data tanpa reload halaman
- plugin atau theme perlu membuka data WordPress ke aplikasi eksternal
- kamu ingin membuat endpoint custom untuk form, dashboard, atau integrasi pihak ketiga
- data yang dikirim lebih cocok sebagai JSON daripada form biasa
- kamu butuh pemisahan yang tegas antara layer UI dan layer data
REST API biasanya kurang cocok kalau:
- aksi bisa ditangani langsung oleh form submit biasa di server-side PHP
- fitur hanya dipakai internal di admin dan tidak butuh route publik
- operasi sangat sederhana dan bisa dijalankan lewat hook biasa atau template logic
- kamu sedang menambah output HTML biasa, bukan resource/data API
Prinsip praktisnya: pakai REST API kalau ada nilai nyata dari struktur request yang formal, output JSON, dan kontrol akses yang jelas.
Cara kerja register route
Route REST API didaftarkan lewat register_rest_route() di hook rest_api_init.
Contoh dasar:
add_action('rest_api_init', function () {
register_rest_route('myplugin/v1', '/books/(?P<id>\d+)', [
'methods' => 'GET',
'callback' => 'myplugin_get_book',
'permission_callback' => '__return_true',
]);
});Apa yang terjadi saat route diregister
- WordPress menjalankan hook
rest_api_init. - Callback kamu memanggil
register_rest_route(). - Namespace dan route disimpan ke registry REST internal.
- Saat request masuk ke path yang cocok, WordPress memilih route yang sesuai.
- WordPress menjalankan permission callback dulu.
- Kalau diizinkan, callback utama dipanggil.
- Hasilnya dibungkus jadi respons REST.
Struktur route
- namespace: versi atau kelompok API, misalnya
myplugin/v1 - route: path spesifik, misalnya
/books/(?P<id>\d+) - args: metode, callback, permission, validasi, dan sanitization
Contoh namespace yang sehat biasanya punya versi, karena kamu hampir pasti akan melakukan perubahan skema respons di masa depan.
Parameter route
WordPress mendukung parameter dinamis lewat regex capture group, misalnya:
register_rest_route('myplugin/v1', '/books/(?P<id>\d+)', [
'methods' => 'GET',
'callback' => 'myplugin_get_book',
]);(?P<id>\d+) menangkap angka sebagai id. Ini berguna untuk resource detail seperti post, book, event, atau order.
Permission callback
permission_callback adalah gerbang utama sebelum callback dijalankan. Ini bukan dekorasi. Ini lapisan kontrol akses yang menentukan apakah request berhak melanjutkan.
Kenapa permission callback penting
Tanpa permission check yang benar, endpoint bisa kebuka ke publik atau memberi akses yang terlalu luas. Karena REST API sering dipakai dari browser, bahaya paling umum justru bukan SQL injection saja, melainkan endpoint terbuka tanpa otorisasi yang tepat.
Pola permission yang umum
1. Publik
Kalau endpoint memang boleh diakses semua orang:
'permission_callback' => '__return_true'Pakai ini hanya kalau datanya memang publik.
2. Login required
Kalau user harus login:
'permission_callback' => function () {
return is_user_logged_in();
}3. Capability-based
Kalau akses harus mengikuti capability:
'permission_callback' => function () {
return current_user_can('edit_posts');
}4. Resource-specific
Kalau akses tergantung objek tertentu:
'permission_callback' => function ($request) {
$post_id = (int) $request['id'];
return current_user_can('edit_post', $post_id);
}Ini lebih sehat karena izin diperiksa terhadap resource yang benar, bukan hanya status login.
Aturan praktis permission
- Jangan anggap
is_user_logged_in()cukup untuk semua kasus. - Jangan buka endpoint admin-only dengan
__return_true. - Jangan letakkan otorisasi hanya di dalam callback utama; permission callback harus memblokir lebih awal.
- Kalau ada data sensitif, cek capability yang spesifik, bukan cuma login.
Nonces di WordPress REST API
Nonce di WordPress dipakai sebagai token keamanan untuk request yang datang dari browser yang sudah punya sesi login. Di REST API, nonce sering dipakai untuk membuktikan bahwa request datang dari context WordPress yang valid, terutama dari admin atau frontend yang memakai cookie auth.
Header nonce yang umum
WordPress REST biasanya memakai header:
X-WP-Nonce: <nonce>Nonce ini biasanya dibuat dari PHP lalu dikirim ke JavaScript, misalnya lewat wp_localize_script() atau wp_add_inline_script().
Kapan nonce dibutuhkan
Nonce dibutuhkan kalau request:
- memakai cookie-based authentication
- berasal dari browser context WordPress
- melakukan aksi yang mengubah data
- harus mengurangi risiko CSRF
Nonce bukan pengganti capability check. Ini penting: nonce memverifikasi request context, capability memverifikasi hak akses.
Nonce bukan password
Jangan memperlakukan nonce sebagai secret jangka panjang. Nonce:
- punya masa berlaku terbatas
- bisa diregenerasi
- tidak dimaksudkan untuk identitas user
- tidak cukup untuk keamanan kalau permission check lemah
Authentication flow
WordPress REST API mendukung beberapa pola autentikasi, dan pilihan yang tepat tergantung siapa yang memanggil endpoint.
1. Cookie authentication
Ini umum dipakai di dalam situs WordPress itu sendiri, terutama dari admin atau frontend yang sudah login.
Alurnya:
- browser membawa cookie login WordPress
- request mengirim
X-WP-Nonce - WordPress memverifikasi nonce dan sesi
- permission callback mengecek capability
- callback dijalankan jika lolos
Ini pola paling umum untuk request AJAX atau interaksi UI di situs yang sama.
2. Application Passwords
Dipakai saat aplikasi eksternal perlu akses ke site WordPress dengan identitas yang jelas. Cocok untuk integrasi server-to-server atau tooling yang tidak berjalan di browser user.
Catatan penting:
- jangan pakai credential admin utama kalau bisa dihindari
- batasi user dan capability yang dipakai
- simpan credential dengan aman
3. OAuth / plugin auth tambahan
Beberapa setup memakai OAuth atau plugin auth khusus. Ini biasanya dipakai kalau integrasi butuh token exchange atau akses terdelegasi.
4. Basic auth untuk kebutuhan dev
Basic auth kadang dipakai saat development atau environment tertentu, tetapi bukan pilihan utama untuk produksi kecuali ada lapisan keamanan tambahan yang jelas.
Alur autentikasi yang sehat
Urutannya biasanya seperti ini:
- client mengirim request ke endpoint
- WordPress mengenali mekanisme auth yang dipakai
- token / nonce / cookie diverifikasi
permission_callbackdievaluasi- callback dijalankan
- response dikembalikan
Alur request → permission → callback → response
Cara membaca alur ini
- Route matching terjadi lebih dulu.
- Permission check selalu datang sebelum callback utama.
- Callback idealnya fokus pada pekerjaan bisnis, bukan otorisasi.
- Respons sebaiknya dibangun sebagai
WP_REST_Response, array, atauWP_Errorsesuai konteks.
Contoh endpoint custom yang lebih lengkap
add_action('rest_api_init', function () {
register_rest_route('myplugin/v1', '/books/(?P<id>\d+)', [
'methods' => 'GET',
'callback' => 'myplugin_get_book',
'permission_callback' => function ($request) {
$book_id = (int) $request['id'];
return current_user_can('read_post', $book_id);
},
'args' => [
'id' => [
'validate_callback' => function ($value) {
return is_numeric($value) && (int) $value > 0;
},
'sanitize_callback' => 'absint',
],
],
]);
});
function myplugin_get_book(WP_REST_Request $request) {
$book_id = (int) $request['id'];
$post = get_post($book_id);
if (!$post || $post->post_type !== 'book') {
return new WP_Error('not_found', 'Buku tidak ditemukan.', ['status' => 404]);
}
return rest_ensure_response([
'id' => $post->ID,
'title' => get_the_title($post),
'status' => $post->post_status,
]);
}Kenapa contoh ini sehat
- namespace punya versi
- route memakai parameter terstruktur
- permission tergantung resource
- argumen divalidasi dan disanitasi
- error respons memakai
WP_Errordengan status yang jelas
Jebakan umum pada request WordPress
1. Lupa menulis permission_callback
Di banyak versi WordPress, endpoint tanpa permission_callback yang jelas akan memicu warning atau perilaku yang tidak diinginkan. Lebih penting lagi, kamu jadi berisiko meluncurkan endpoint tanpa kontrol akses yang eksplisit.
2. Mengandalkan nonce tanpa capability check
Nonce hanya melindungi konteks request, bukan hak akses penuh. Kalau user tidak boleh melakukan aksi itu, tetap harus dicek capability-nya.
3. Mengira is_user_logged_in() cukup
Login bukan berarti user berhak melakukan semua aksi. Pakai capability yang sesuai resource.
4. Tidak menyetel methods
Endpoint yang seharusnya hanya GET bisa kebuka untuk POST, PUT, atau DELETE kalau metode tidak dibatasi dengan benar.
5. Tidak memvalidasi parameter route
Jangan langsung percaya pada nilai dari URL, query string, atau body. Validasi dan sanitasi tetap wajib.
6. Response format tidak konsisten
Kalau satu endpoint mengembalikan array mentah, endpoint lain mengembalikan HTML, dan yang lain lagi campur-campur, konsumsi API jadi sulit. Jaga struktur respons tetap konsisten.
7. Mengirim terlalu banyak logika ke callback
Callback yang besar biasanya sulit dirawat. Pisahkan validasi, query, transformasi data, dan otorisasi ke bagian yang jelas.
8. Lupa perbedaan context browser dan server
Request dari browser mungkin punya cookie dan nonce. Request dari luar site biasanya tidak. Auth flow harus disesuaikan dengan siapa client-nya.
9. Tidak memperhatikan caching dan header
Data yang sensitif atau user-specific tidak selalu aman kalau diperlakukan seperti response publik yang bisa di-cache sembarangan.
Catatan implementasi
Struktur callback yang sehat
- callback fokus menghasilkan data
- permission callback fokus menentukan izin
- validasi fokus memeriksa input
- sanitization fokus membersihkan nilai sebelum dipakai
Praktik yang aman
- pakai namespace versi:
vendor/v1 - cek capability spesifik untuk aksi yang mengubah data
- kembalikan error dengan status HTTP yang tepat
- gunakan
rest_ensure_response()untuk normalisasi respons - perlakukan nonce sebagai lapisan tambahan, bukan satu-satunya pengaman
Saat memilih auth flow
- Situs sendiri, browser sendiri → cookie auth + nonce
- Aplikasi eksternal → application password atau mekanisme token yang memang disiapkan
- Integrasi machine-to-machine → credential dan capability yang dibatasi
Ringkasan cepat
- REST API dipakai saat kamu butuh data/aksi berbasis HTTP JSON, bukan render HTML.
- Route diregister lewat
rest_api_initdanregister_rest_route(). permission_callbackharus menjadi gerbang akses utama.- Nonce membantu proteksi request browser, tapi bukan pengganti authorization.
- Auth flow yang benar selalu menggabungkan identitas, nonce/token, permission, dan respons yang konsisten.
Referensi terkait
- WordPress Hooks: Actions, Filters, Priorities, Callbacks, dan Hook Debugging
- WordPress Custom Post Types, Taxonomies, Meta Fields, dan Admin UI
- WordPress Theme Hierarchy, Template Files, Loop, dan Enqueue Assets