D
Engineering

Auth & JWT

JWT validasi-only — token diterbitkan dazoapp. Middleware verifyToken dengan IP allowlist bypass via x-forwarded-for (spoofable). Tenant authorization belum diterapkan — store_id tidak dicocokkan dengan claims.

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):

js
const protectedRoutes = Router();
protectedRoutes.use(verifyToken);

Alur validasi (authMiddleware.js:5-29):

text
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:

js
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

js
const verified = jwt.verify(token.replace('Bearer ', ''), env.jwtSecret);
req.user = verified;

jwt.verify memverifikasi signature + expiry. Jika invalid, return 403:

json
{
  "message": "Token tidak valid."
}

Claims

Setelah valid, claims di-cache:

js
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:

RouteAuthPemanggil
GET /api/test✅ JWT atau IP allowlistSmoke test
POST /api/chatbot-api✅ JWT atau IP allowlistbackend-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

RouteAuthCatatan
GET /health❌ publicHealth check, di luar /api

Response error

StatusKondisiBody
401Token kosong{"message": "Akses ditolak. Token tidak ditemukan."}
403Token invalid/expired{"message": "Token tidak valid."}

Verifikasi token lokal

bash
# 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

AreaLokasi
jwtSecretconfig/env.js — wajib sync dengan dazoapp + backend-go
Algoritma HS256Kontrak penerbitan dazoapp
Payload tokensub, userLevel, dll. dari dazoapp
allowedIPJika diubah, IP internal bisa ditolak

Langkah berikutnya