Perbaikan verifyBearerToken
Perbaikan verifyBearerToken
Section titled “Perbaikan verifyBearerToken”Token hanya dari header, pesan galat seragam.
Berkas: alat/hari-3/Praktik 9/perbaikan/verifyBearerToken.js
// =====================================================================// Praktik 9 - versi perbaikan verifyBearerToken.js//// Perubahan dari versi modul://// 1. getTokenParams() DIHAPUS. Menerima token dari query string berarti// token ikut tercatat di access log Nginx, log Cloud Build, history// browser, dan header Referer saat halaman memuat resource lain.//// 2. requireAuth() sekarang memeriksa token lebih dahulu sebelum apa pun,// dan mengembalikan bentuk hasil yang konsisten.//// 3. Ada pesan galat yang tidak membocorkan alasan sebenarnya. Versi modul// membedakan "token tidak ditemukan" dan "token tidak valid", yang// membantu penyerang menebak. Untuk klien cukup satu pesan 401.//// 4. Ada pemeriksaan bentuk payload. jwt.verify() bisa mengembalikan string// (kalau token ditandatangani dengan secret berbentuk string), dan// payload.role bisa tidak ada. Tanpa pemeriksaan ini, hasRequiredRole()// akan membandingkan undefined dan mengembalikan false, tetapi pesan// galatnya menyesatkan.//// Letakkan berkas ini di: src/lib/auth/verifyBearerToken.js// =====================================================================
import { verifyAccessToken } from "./jwt";import { hasRequiredRole } from "./roles";
// Mengambil token hanya dari header "Authorization: Bearer <token>".// Tidak ada lagi jalur lewat query string.export function getBearerToken(request) { const authHeader = request.headers.get("authorization"); if (!authHeader) return null;
const [skema, nilai] = authHeader.split(" "); if (!skema || skema.toLowerCase() !== "bearer") return null; if (!nilai || !nilai.trim()) return null; return nilai.trim();}
/** * @returns {{ payload: object } | { error: string, status: number }} */export function requireAuth(request, minRole = null) { const token = getBearerToken(request);
// Pesan dan status dibuat seragam untuk semua kegagalan autentikasi. // Klien tidak perlu tahu apakah tokennya kosong, kadaluarsa, atau salah // tanda tangan — yang penting dia harus login ulang. if (!token) { return { error: "Unauthorized", status: 401 }; }
let payload; try { payload = verifyAccessToken(token); } catch { return { error: "Unauthorized", status: 401 }; }
// jwt.verify bisa mengembalikan string untuk token dengan payload berupa // string biasa. Pastikan bentuknya objek sebelum dipakai. if (typeof payload !== "object" || payload === null) { return { error: "Unauthorized", status: 401 }; }
if (typeof payload.role !== "string" || !payload.role) { return { error: "Unauthorized", status: 401 }; }
if (minRole && !hasRequiredRole(payload.role, minRole)) { // 403 di sini benar: tokennya sah, hanya haknya kurang. return { error: "Forbidden: Akses ditolak", status: 403 }; }
return { payload };}