engine-bot tidak menerbitkan JWT. Token diterbitkan dazoapp (Laravel) dan divalidasi di sini via middleware/authMiddleware.js:verifyToken.
Middleware — verifyToken
Diterapkan global pada group /api (routes/chatbotRoutes.js:11):
const protectedRoutes = Router();
protectedRoutes.use(verifyToken);Alur validasi (authMiddleware.js:5-29):
1. IP allowlist check
└─ jika IP di env.allowedIP → bypass auth (next())
2. Token presence check
└─ jika Authorization kosong → 401 "Akses ditolak. Token tidak ditemukan."
3. Parse + verify JWT (HS256, jwtSecret)
└─ jika invalid/expired → 403 "Token tidak valid."
4. Cache claims di req.user
5. next()IP allowlist bypass
authMiddleware.js:6-12 — IP client dicek terhadap env.allowedIP (comma-split dari config/env.js). Jika match, request bypass auth sepenuhnya.
Pembacaan IP:
const clientIP = req.headers["x-forwarded-for"] || req.ip || req.connection.remoteAddress;
if (allowedIPs.includes(clientIP)) {
console.log(`Bypassed auth for IP: ${clientIP}`);
return next();
}Verifikasi JWT
const verified = jwt.verify(token.replace('Bearer ', ''), env.jwtSecret);
req.user = verified;jwt.verify memverifikasi signature + expiry. Jika invalid, return 403:
{
"message": "Token tidak valid."
}Claims
Setelah valid, claims di-cache:
req.user = verified; // jwt.Claims (decoded payload)Tidak ada helper yang membaca spesifik claim. Implementasi tenant authorization belum ada.
Tenant authorization belum diterapkan
Route yang dilindungi
Semua route /api aktif melewati verifyToken:
| Route | Auth | Pemanggil |
|---|---|---|
GET /api/test | ✅ JWT atau IP allowlist | Smoke test |
POST /api/chatbot-api | ✅ JWT atau IP allowlist | backend-go |
POST /api/ai-agent-testing | ✅ | Developer |
POST /api/notify-new-message | ✅ | backend-go / internal |
POST /api/generate_welcome | ✅ | backend-go |
POST /api/webhook/payment-notification | ✅ | dazoapp |
Route yang tidak dilindungi
| Route | Auth | Catatan |
|---|---|---|
GET /health | ❌ public | Health check, di luar /api |
Response error
| Status | Kondisi | Body |
|---|---|---|
| 401 | Token kosong | {"message": "Akses ditolak. Token tidak ditemukan."} |
| 403 | Token invalid/expired | {"message": "Token tidak valid."} |
Verifikasi token lokal
# Generate token dari dazoapp
php artisan tinker
>>> JWTAuth::fromUser(User::first());
# Test ke engine-bot
curl -X POST http://localhost:1313/api/chatbot-api \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"store_id":"store-1","customer_id":"628123456789","agent_id":"agent-1","question":"Halo","time_reply":2}'Socket.IO — tidak ter-autentikasi
Yang TIDAK boleh diubah tanpa koordinasi
| Area | Lokasi |
|---|---|
jwtSecret | config/env.js — wajib sync dengan dazoapp + backend-go |
| Algoritma HS256 | Kontrak penerbitan dazoapp |
| Payload token | sub, userLevel, dll. dari dazoapp |
allowedIP | Jika diubah, IP internal bisa ditolak |
Langkah berikutnya
- Cara tenant dipisah? Baca Multi-tenant.
- Pola kode? Baca Conventions.