Autentikasi dan Sesi
Pendahuluan
Dokumen ini menjelaskan alur autentikasi frontend, penyimpanan sesi cookie, perlindungan rute, penanganan izin, dan perilaku logout.
Alur Login
Halaman login adalah src/pages/LoginPage.tsx.
Alur tingkat tinggi:
- Kredensial: Pengguna mengirimkan email dan kata sandi.
- Panggilan API: Halaman memanggil
api.auth.login(credentials). - Ekstraksi Data: Jika berhasil, halaman mengekstrak
token,user.id, danuser.organizationId. - Penyimpanan Sesi: Halaman memanggil
auth.setAuth(...). - Navigasi: Halaman menunjukkan umpan balik sukses dan menavigasi ke
/dashboard.
Respons login yang diharapkan bertipe:
interface AuthResponse {
token: string;
user: User;
}
Frontend mengharapkan backend mengembalikan respons ini di dalam pembungkus API standar:
interface ApiResponse<T> {
success: boolean;
data: T;
errors: string[];
traceId?: string | null;
}
Penyimpanan Cookie
Penyimpanan sesi dikelola oleh src/lib/auth.ts dengan js-cookie.
| Kunci Cookie | Konstanta Sumber | Tujuan |
|---|---|---|
access_token | COOKIE_KEYS.ACCESS_TOKEN | Token bearer untuk panggilan API |
user_id | COOKIE_KEYS.USER_ID | ID pengguna saat ini |
organization_id | COOKIE_KEYS.ORGANIZATION_ID | Cakupan organisasi saat ini |
user_name | COOKIE_KEYS.USER_NAME | Konstanta cadangan, tidak digunakan di alur utama |
user_email | COOKIE_KEYS.USER_EMAIL | Konstanta cadangan, tidak digunakan di alur utama |
Opsi cookie:
| Opsi | Nilai |
|---|---|
secure | true ketika protokol halaman saat ini HTTPS |
sameSite | strict |
expires | 7 hari |
Perlindungan Rute (Route Protection)
PrivateRoutes di src/app/PrivateRoutes.tsx melindungi semua rute /dashboard.
Guard menggunakan pemeriksaan ini saja:
auth.isAuthenticated()
isAuthenticated() mengembalikan nilai true ketika access_token ada di cookie. Validitas token ditegakkan oleh backend pada panggilan API, bukan dengan mendekode token di sisi klien.
Autentikasi API
src/lib/api.ts membuat instans Axios terpusat. Interceptor permintaan membaca auth.getToken() dan melampirkan:
Authorization: Bearer <token>
Interceptor respons menangani HTTP 401:
- Bersihkan cookie auth.
- Alihkan browser ke
/. - Tolak promise permintaan asli.
Klien streaming chat analitik di src/lib/analyticsChat.ts menggunakan fetch daripada Axios, tetapi mengikuti aturan token yang sama dan membersihkan sesi pada 401.
Pengguna Saat Ini dan Izin
src/hooks/useApi.ts mengekspos useUserPermissions().
Hook tersebut:
- Memeriksa
auth.isAuthenticated(). - Memanggil
api.auth.me(). - Membaca izin dari
user.role.permissions. - Mengekspos
hasPermission(slug).
Slug izin dipusatkan di src/lib/constants.ts:
| Domain | Slug |
|---|---|
| Sensors | create-sensor, update-sensor, delete-sensor, read-sensor |
| Users | create-user, edit-user, delete-user, read-user |
| Roles | create-role, edit-role, delete-role, read-role |
| Organization | edit-organization |
Layar fitur menggunakan slug ini untuk menampilkan atau menyembunyikan tindakan buat, edit, dan hapus. Backend tetap bertanggung jawab atas penegakan otorisasi akhir.
Alur Logout
Logout dipicu dari menu pengguna shell dasbor.
Alur:
- Konfirmasi: Tampilkan dialog konfirmasi melalui
showConfirm. - Panggilan API: Panggil
api.auth.logout(). - Pembersihan Sesi: Bersihkan cookie auth dengan
auth.clearAuth(). - Umpan Balik: Tampilkan pesan sukses.
- Navigasi: Navigasi ke
/.
Jika panggilan logout backend gagal, frontend tetap membersihkan data auth lokal dan menavigasi ke /.
Mode Kegagalan Sesi
| Skenario | Perilaku Frontend |
|---|---|
| Token hilang sebelum masuk dasbor | Alihkan ke / |
API mengembalikan 401 | Bersihkan cookie dan alihkan ke / |
/auth/me gagal di hook izin | Daftar izin menjadi kosong |
| API logout gagal | Auth lokal tetap dibersihkan |
| Cookie ID pengguna hilang di shell | Shell melewati pengambilan data pengguna saat ini |
Catatan Keamanan
- Frontend menyimpan token bearer di cookie, bukan di
localStorage. - Cookie bersifat
sameSite: strict, mengurangi risiko permintaan lintas situs (CSRF). - Bendera
securebergantung pada penyajian aplikasi melalui HTTPS. - Frontend tidak mengimplementasikan penyegaran token (token refresh).
- Frontend tidak mendekode klaim JWT; ia bergantung pada titik akhir backend untuk pengguna saat ini dan izin.