Skip to content

Tautan Mati di Sidebar Admin: Menu yang Selalu 403 Harus Dibuang

Adityo Guni Waluyo

Audit nav menemukan dua menu yang selalu berakhir 403 dan tujuh item yang masih berkata baca saja. Keduanya dibuang, dan ketiadaannya ikut diuji.

Ringkasan

Sidebar admin error. Menu navigasi tidak berfungsi. Perbaikan dilakukan di frontend.

Sidebar admin KotaPortal, akun bidang Layanan. Saya klik "Menu Navigasi", yang terbuka halaman 403 dengan latar putih polos. Bukan toast, bukan halaman kosong tanpa keterangan. Kode status telanjang. Saya coba "Pengaturan Situs", hasilnya identik.

Yang membuat saya bertahan di situ bukan 403-nya, tapi tidak ada satu pun yang terlihat salah. Menu itu duduk di posisi yang sama seperti menu lain, tipografinya sama, urutannya rapi. Saya sempat mengira akun uji saya yang rusak.

Kecurigaan Pertama Salah

Dugaan awal saya: backend lupa di-scope per bidang. Anggapan itu keliru, dan commit ef43ed0 mencatatnya tanpa basa-basi. Kedua menu membungkus setiap endpoint dengan RequireGlobalBidang. Tidak ada bug otorisasi di sana. Yang bermasalah adalah sidebar yang menawarkan pintu yang sejak awal dikunci, kepada semua akun, dengan tampilan yang meyakinkan.

Audit nav janggal di commit yang sama menemukan hal kedua, dan ini yang lebih mengganggu. Delapan item di grup Fungsi, tujuh di antaranya sudah di-scope per bidang di backend. Informasi, Ulasan, Layanan, Tipe Layanan, Paket Sewa, Saran & Kritik, Media. Artinya departemen pemilik memang punya hak tulis di ketujuhnya.

Tapi ketujuhnya masih memakai penanda mata plus nama aksesibel "(baca saja)". Selama ini saya membacanya sebagai "kamu cuma boleh melihat". Saya salah membaca UI saya sendiri, dan cukup lama. Tidak ada yang rusak secara fungsional. Yang rusak adalah janji yang tertulis di layar. [1] NN/g menyebut tautan sebagai janji: "Any broken promise, large or small, chips away at trust and credibility." Penanda "baca saja" pada menu yang sebenarnya bisa ditulis adalah janji yang sama-sama tidak ditepati, cuma arahnya kebalikan.

Satu Flag dan Satu Set

Perbaikannya kecil: commit ef43ed0 mengubah dua file, total +82/-31 baris, dan sisanya ada di layout.tsx folder admin CMS serta spek e2e-nya. Flag baru bidangSlice?: boolean dipasang di tujuh dari delapan item. Persyaratan Dokumen sengaja tidak dipasangi karena memang lintas bidang, dipakai semua departemen.

Untuk dua menu mematikan itu, saya tidak menyembunyikannya satu per satu di JSX. Satu Set berisi dua href, GLOBAL_ONLY_HREFS, disaring di dalam buildNavGroups(bidang, permissions) untuk setiap akun yang bukan isAll. Akun lintas bidang tetap melihat keduanya. Akun bidang tidak lagi, di halaman mana pun.

Grup "Fungsi — Lintas (Sementara)" dihapus seluruhnya. Kata "Sementara" sudah bertahan terlalu lama untuk sesuatu yang tidak pernah ditinjau ulang, dan tiap kali saya membuka sidebar, grup itu memakan ruang visual yang sama besar dengan grup yang benar-benar relevan. Sisa satu grup kecil, "Fungsi Lintas", isinya Persyaratan Dokumen, dan grup itu hanya dirender kalau tidak kosong.

Kenapa Cukup di Frontend

Pertanyaan yang wajar: kalau ini soal 403, kenapa tidak backend saja yang diperbaiki? Karena penegakan tidak pernah pindah. Commit menyatakan tidak perlu security review, sebab yang berubah hanya label dan pengelompokan; penolakan akses tetap terjadi di backend. [2] OWASP menegaskan hal yang sama: pengecekan di sisi klien tidak boleh menjadi penentu, dan izin harus divalidasi pada setiap request.

Menyembunyikan tautan bukan pengganti otorisasi, dan bukan itu yang dikerjakan di sini. [3] Panduan autentikasi Next.js mengingatkan bahwa pengecekan di layout tidak dijalankan ulang saat navigasi, jadi pemeriksaan sesi harus diletakkan dekat sumber data. Sidebar yang tahu nama bidang bukan tempat memutuskan akses, hanya tempat menampilkan apa yang relevan.

Ada satu hal yang saya ubah di kepala saya sendiri: menu yang tidak bisa dipakai akun tertentu bukan "menu dengan izin terbatas". Ia tautan mati, dan tautan mati tidak punya tempat di daftar navigasi.

Tes yang Menguji Ketiadaan

Bagian yang biasanya dilewatkan justru di sini. Tes di modules-nav.spec.ts sekarang menguji ketiadaan, bukan hanya kehadiran. toHaveCount(0) untuk "Menu Navigasi" dan "Pengaturan Situs" pada akun ter-scope. toHaveCount(0) juga untuk nama aksesibel lama "(baca saja)".

Tanpa tes ketiadaan, perbaikan seperti ini akan kembali dalam hitungan bulan. Seseorang menambah satu href ke grup, semua tes tetap hijau, dan tautan 403 itu muncul lagi tanpa ada yang sadar.

Kehadiran tetap dikunci: aria-expanded="true" untuk grup Fungsi Lintas yang terbuka di desktop, dan pada mobile-chrome tautannya dirender sebagai tautan biasa, bukan tombol yang membuka submenu yang tidak ada. [4] WCAG 2.4.4 soal tujuan tautan menyebut pengguna harus bisa memutuskan mau mengikuti tautan atau tidak, dan teknologi bantu mengekspos daftar tautan halaman. Tautan yang selalu berakhir 403 mengisi daftar itu dengan janji palsu. Bagi pengguna screen reader, itu bukan masalah kosmetik.

Yang berubah bukan cuma sidebar. Sekarang setiap item nav harus lulus satu pertanyaan sebelum masuk daftar: akun ini klik, lalu dapat apa. Kalau jawabannya 403, item itu tidak punya alasan untuk ada.

Sumber:

  1. Nielsen Norman Group: A Link is a Promise
  2. OWASP Cheat Sheet Series: Authorization
  3. Next.js: How to implement authentication in Next.js
  4. W3C: Understanding Success Criterion 2.4.4 Link Purpose (In Context)

Artikel terkait