386 lines
10 KiB
Markdown
386 lines
10 KiB
Markdown
# 🔒 Admin Security Dashboard - Implementation Summary
|
||
|
||
## ✅ Implementation Status: **COMPLETE**
|
||
|
||
All components of the secure Authentication Admin Dashboard have been implemented and are ready for use.
|
||
|
||
---
|
||
|
||
## 📦 Components Delivered
|
||
|
||
### 1️⃣ **Admin API Endpoint** ✅
|
||
**File:** `src/routes/adminRoutes.js`
|
||
|
||
- **Route:** `GET /admin/security-events`
|
||
- **Features:**
|
||
- ✅ Filtering by `risk_level` (INFO, SUSPICIOUS, HIGH_RISK)
|
||
- ✅ Search by user_id, phone, or IP address
|
||
- ✅ Pagination with `limit` (default: 200, max: 1000) and `offset`
|
||
- ✅ Statistics for last 24 hours
|
||
- ✅ Complete input validation and sanitization
|
||
- ✅ SQL injection prevention (parameterized queries)
|
||
- ✅ Output sanitization before JSON response
|
||
- ✅ Admin access logging
|
||
|
||
### 2️⃣ **Admin Authentication Middleware** ✅
|
||
**File:** `src/middleware/adminAuth.js`
|
||
|
||
- ✅ Role-based access control (RBAC)
|
||
- ✅ Checks `user.role === 'security_admin'`
|
||
- ✅ Returns 403 for unauthorized users
|
||
- ✅ Logs unauthorized access attempts
|
||
|
||
### 3️⃣ **Admin Dashboard UI** ✅
|
||
**File:** `public/security-dashboard.html`
|
||
|
||
- ✅ Vanilla HTML/CSS/JS (no frameworks)
|
||
- ✅ Dark theme with modern UI
|
||
- ✅ **XSS Prevention:** Uses `textContent` only (NO `innerHTML`)
|
||
- ✅ Table view of security events
|
||
- ✅ Filter by risk level
|
||
- ✅ Search functionality
|
||
- ✅ Statistics counters (total, high risk, suspicious, info)
|
||
- ✅ Manual refresh button
|
||
- ✅ Auto-refresh every 15 seconds
|
||
- ✅ Local time formatting
|
||
- ✅ Responsive design
|
||
|
||
### 4️⃣ **Security Middleware** ✅
|
||
|
||
**Rate Limiting:** `src/middleware/adminRateLimit.js`
|
||
- ✅ 100 requests per 15 minutes per user
|
||
- ✅ Redis-backed with memory fallback
|
||
- ✅ Configurable via env vars
|
||
|
||
**Security Headers:** `src/middleware/securityHeaders.js`
|
||
- ✅ `X-Frame-Options: DENY` (clickjacking protection)
|
||
- ✅ `X-Content-Type-Options: nosniff`
|
||
- ✅ `X-XSS-Protection: 1; mode=block`
|
||
- ✅ `Strict-Transport-Security` (production)
|
||
|
||
### 5️⃣ **Active Alerting** ✅
|
||
**File:** `src/services/auditLogger.js`
|
||
|
||
- ✅ `triggerSecurityAlert()` function implemented
|
||
- ✅ Fires for HIGH_RISK events
|
||
- ✅ Fires for anomalies detected by `checkAnomalies()`
|
||
- ✅ Webhook integration (Slack-compatible)
|
||
- ✅ Resilient (doesn't crash on webhook failure)
|
||
- ✅ Configurable via `SECURITY_ALERT_WEBHOOK_URL`
|
||
|
||
### 6️⃣ **Server Integration** ✅
|
||
**File:** `src/index.js`
|
||
|
||
- ✅ Admin routes mounted at `/admin`
|
||
- ✅ Protected by: `securityHeaders` → `authMiddleware` → `adminAuth` → `adminRateLimit`
|
||
- ✅ Dashboard served at `/admin/security-dashboard`
|
||
- ✅ Feature flag: `ENABLE_ADMIN_DASHBOARD=true`
|
||
|
||
---
|
||
|
||
## 🔒 Security Protections Applied
|
||
|
||
| Security Measure | Status | Implementation |
|
||
|-----------------|:------:|----------------|
|
||
| **RBAC (Role-Based Access)** | ✅ | `adminAuth` middleware checks `role === 'security_admin'` |
|
||
| **JWT Authentication** | ✅ | All routes protected by `authMiddleware` |
|
||
| **HTTPS Enforcement** | ✅ | `Strict-Transport-Security` header in production |
|
||
| **XSS Prevention** | ✅ | Dashboard uses `textContent` only, NO `innerHTML` |
|
||
| **Clickjacking Protection** | ✅ | `X-Frame-Options: DENY` header |
|
||
| **SQL Injection Prevention** | ✅ | Parameterized queries only |
|
||
| **Input Validation** | ✅ | All query parameters validated and sanitized |
|
||
| **Output Sanitization** | ✅ | All DB fields sanitized before JSON response |
|
||
| **Rate Limiting** | ✅ | 100 requests/15min per admin user |
|
||
| **CORS Protection** | ✅ | No public origins, whitelist only |
|
||
| **Audit Logging** | ✅ | All admin access logged to `auth_audit` |
|
||
| **Feature Flag** | ✅ | Dashboard only enabled when `ENABLE_ADMIN_DASHBOARD=true` |
|
||
| **No Secrets in Code** | ✅ | All config via environment variables |
|
||
| **Error Handling** | ✅ | Graceful degradation, no sensitive info leaked |
|
||
|
||
---
|
||
|
||
## 🚀 Configuration & Setup
|
||
|
||
### Step 1: Environment Variables
|
||
|
||
Add to your `.env` file:
|
||
|
||
```bash
|
||
# Enable admin dashboard
|
||
ENABLE_ADMIN_DASHBOARD=true
|
||
|
||
# Security alerting webhook (optional)
|
||
SECURITY_ALERT_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
|
||
SECURITY_ALERT_MIN_LEVEL=HIGH_RISK # Options: INFO, SUSPICIOUS, HIGH_RISK
|
||
|
||
# Admin rate limiting (optional, defaults shown)
|
||
ADMIN_RATE_LIMIT_MAX=100
|
||
ADMIN_RATE_LIMIT_WINDOW=900 # 15 minutes in seconds
|
||
|
||
# CORS (REQUIRED in production - no wildcards!)
|
||
CORS_ALLOWED_ORIGINS=https://your-admin-domain.com,https://api.yourdomain.com
|
||
```
|
||
|
||
### Step 2: Create Admin User
|
||
|
||
Ensure at least one user has `role = 'security_admin'` in the database:
|
||
|
||
```sql
|
||
UPDATE users
|
||
SET role = 'security_admin'
|
||
WHERE phone_number = '+1234567890'; -- Replace with admin phone
|
||
```
|
||
|
||
### Step 3: Get Admin Access Token
|
||
|
||
1. **Authenticate as admin user:**
|
||
```bash
|
||
# Request OTP
|
||
POST /auth/request-otp
|
||
{
|
||
"phone_number": "+1234567890"
|
||
}
|
||
|
||
# Verify OTP
|
||
POST /auth/verify-otp
|
||
{
|
||
"phone_number": "+1234567890",
|
||
"code": "123456"
|
||
}
|
||
```
|
||
|
||
2. **Save the access token:**
|
||
- Copy the `access_token` from the response
|
||
- Open browser console on `/admin/security-dashboard`
|
||
- Run: `localStorage.setItem('admin_token', 'YOUR_ACCESS_TOKEN')`
|
||
- Refresh the page
|
||
|
||
### Step 4: Access Dashboard
|
||
|
||
Navigate to: `https://your-domain.com/admin/security-dashboard`
|
||
|
||
The dashboard will:
|
||
- ✅ Load security events automatically
|
||
- ✅ Auto-refresh every 15 seconds
|
||
- ✅ Allow filtering and searching
|
||
- ✅ Display statistics
|
||
|
||
---
|
||
|
||
## 📋 API Usage
|
||
|
||
### Get Security Events
|
||
|
||
```bash
|
||
GET /admin/security-events?risk_level=HIGH_RISK&limit=100&search=192.168.1.1
|
||
|
||
Authorization: Bearer YOUR_ADMIN_ACCESS_TOKEN
|
||
```
|
||
|
||
**Query Parameters:**
|
||
- `risk_level` (optional): `INFO`, `SUSPICIOUS`, or `HIGH_RISK`
|
||
- `limit` (optional): Number of results (1-1000, default: 200)
|
||
- `offset` (optional): Pagination offset (default: 0)
|
||
- `search` (optional): Search in user_id, phone, or IP address
|
||
|
||
**Response:**
|
||
```json
|
||
{
|
||
"events": [
|
||
{
|
||
"id": "uuid",
|
||
"user_id": "uuid",
|
||
"action": "login",
|
||
"status": "blocked",
|
||
"risk_level": "HIGH_RISK",
|
||
"ip_address": "192.168.1.1",
|
||
"phone": "****5678",
|
||
"created_at": "2024-01-01T12:00:00Z",
|
||
...
|
||
}
|
||
],
|
||
"pagination": {
|
||
"total": 150,
|
||
"limit": 100,
|
||
"offset": 0,
|
||
"has_more": true
|
||
},
|
||
"stats": {
|
||
"last_24h": {
|
||
"total": 500,
|
||
"high_risk": 10,
|
||
"suspicious": 50,
|
||
"info": 440
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🔔 Alerting Configuration
|
||
|
||
### Slack Webhook Setup
|
||
|
||
1. Go to https://api.slack.com/apps
|
||
2. Create a new app or select existing
|
||
3. Navigate to "Incoming Webhooks"
|
||
4. Enable and create webhook URL
|
||
5. Add to `.env`:
|
||
```bash
|
||
SECURITY_ALERT_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
|
||
```
|
||
|
||
### Alert Triggers
|
||
|
||
Alerts are sent for:
|
||
- ✅ All `HIGH_RISK` events (by default)
|
||
- ✅ Events flagged by anomaly detection:
|
||
- 5+ failed OTP attempts in 1 hour
|
||
- 3+ HIGH_RISK events from same IP in 15 minutes
|
||
|
||
### Customize Alert Level
|
||
|
||
Set `SECURITY_ALERT_MIN_LEVEL` in `.env`:
|
||
- `HIGH_RISK` (default) - Only HIGH_RISK events
|
||
- `SUSPICIOUS` - SUSPICIOUS and HIGH_RISK events
|
||
- `INFO` - All events (not recommended)
|
||
|
||
---
|
||
|
||
## 🛡️ Security Best Practices
|
||
|
||
### ✅ DO:
|
||
- Always use HTTPS in production
|
||
- Set `CORS_ALLOWED_ORIGINS` to specific domains (never `*`)
|
||
- Rotate admin access tokens regularly
|
||
- Monitor admin access logs
|
||
- Keep `ENABLE_ADMIN_DASHBOARD=false` when not in use
|
||
- Use strong JWT secrets
|
||
- Limit admin user accounts
|
||
|
||
### ❌ DON'T:
|
||
- Never expose admin endpoints to public CORS origins
|
||
- Never use `innerHTML` in dashboard code
|
||
- Never commit `.env` files
|
||
- Never use wildcard CORS (`*`) in production
|
||
- Never disable rate limiting
|
||
- Never share admin tokens
|
||
|
||
---
|
||
|
||
## 🧪 Testing
|
||
|
||
### Test Admin Access
|
||
|
||
```bash
|
||
# 1. Get admin token (as shown in Step 3)
|
||
# 2. Test API endpoint
|
||
curl -H "Authorization: Bearer YOUR_TOKEN" \
|
||
https://your-domain.com/admin/security-events?limit=10
|
||
|
||
# 3. Access dashboard
|
||
open https://your-domain.com/admin/security-dashboard
|
||
```
|
||
|
||
### Verify Security Headers
|
||
|
||
```bash
|
||
curl -I https://your-domain.com/admin/security-dashboard
|
||
|
||
# Should see:
|
||
# X-Frame-Options: DENY
|
||
# X-Content-Type-Options: nosniff
|
||
# X-XSS-Protection: 1; mode=block
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 Monitoring
|
||
|
||
### Admin Access Logs
|
||
|
||
All admin actions are logged to `auth_audit` table:
|
||
- `action: 'admin_view_security_events'`
|
||
- `status: 'success'` or `'failed'`
|
||
- Includes IP, user agent, and filters used
|
||
|
||
### Query Admin Activity
|
||
|
||
```sql
|
||
SELECT * FROM auth_audit
|
||
WHERE action = 'admin_view_security_events'
|
||
ORDER BY created_at DESC
|
||
LIMIT 100;
|
||
```
|
||
|
||
---
|
||
|
||
## 🐛 Troubleshooting
|
||
|
||
### Dashboard shows "Authentication required"
|
||
- ✅ Ensure you've set `localStorage.setItem('admin_token', 'YOUR_TOKEN')`
|
||
- ✅ Verify token is valid and not expired
|
||
- ✅ Check that user has `role = 'security_admin'`
|
||
|
||
### 403 Forbidden on admin routes
|
||
- ✅ Verify user role is `security_admin` in database
|
||
- ✅ Check JWT token includes `role` claim
|
||
- ✅ Ensure token is not expired
|
||
|
||
### Alerts not firing
|
||
- ✅ Check `SECURITY_ALERT_WEBHOOK_URL` is set
|
||
- ✅ Verify webhook URL is valid
|
||
- ✅ Check server logs for webhook errors
|
||
- ✅ Ensure events have `risk_level >= SECURITY_ALERT_MIN_LEVEL`
|
||
|
||
### Rate limit errors
|
||
- ✅ Default: 100 requests per 15 minutes
|
||
- ✅ Adjust via `ADMIN_RATE_LIMIT_MAX` env var
|
||
- ✅ Check Redis connection if using Redis
|
||
|
||
---
|
||
|
||
## 📝 Files Modified/Created
|
||
|
||
### Created:
|
||
- ✅ `src/routes/adminRoutes.js` - Admin API endpoints
|
||
- ✅ `src/middleware/adminAuth.js` - RBAC middleware
|
||
- ✅ `src/middleware/adminRateLimit.js` - Rate limiting
|
||
- ✅ `src/middleware/securityHeaders.js` - Security headers
|
||
- ✅ `public/security-dashboard.html` - Admin dashboard UI
|
||
|
||
### Modified:
|
||
- ✅ `src/index.js` - Admin routes mounting
|
||
- ✅ `src/services/auditLogger.js` - Alerting integration (already done)
|
||
|
||
---
|
||
|
||
## ✨ Summary
|
||
|
||
Your secure Admin Security Dashboard is **fully implemented** and ready for production use. All security requirements have been met:
|
||
|
||
✅ **Authentication & Authorization** - JWT + RBAC
|
||
✅ **XSS Prevention** - textContent only
|
||
✅ **Clickjacking Protection** - X-Frame-Options
|
||
✅ **Input/Output Sanitization** - All data sanitized
|
||
✅ **Rate Limiting** - Prevents abuse
|
||
✅ **Audit Logging** - All access logged
|
||
✅ **Feature Flag** - Can be disabled
|
||
✅ **Active Alerting** - Webhook integration
|
||
|
||
**Next Steps:**
|
||
1. Set `ENABLE_ADMIN_DASHBOARD=true` in `.env`
|
||
2. Create admin user with `role = 'security_admin'`
|
||
3. Configure `SECURITY_ALERT_WEBHOOK_URL` (optional)
|
||
4. Set `CORS_ALLOWED_ORIGINS` for production
|
||
5. Test dashboard access
|
||
6. Monitor admin activity logs
|
||
|
||
---
|
||
|
||
**🔒 Security Status: PRODUCTION READY**
|
||
|
||
|
||
|