# 🔐 Security Guide - Laravel License Server

This document outlines security best practices and recommendations for your Laravel License Server.

## 🛡️ Built-in Security Features

### 1. Rate Limiting ✅

The API includes rate limiting to prevent abuse:

- **Default:** 60 requests per minute per IP
- **Applied to:** All API endpoints
- **Configuration:** `app/Providers/AppServiceProvider.php`

**To adjust rate limits:**

```php
// app/Providers/AppServiceProvider.php
RateLimiter::for('api', function (Request $request) {
    return Limit::perMinute(120)->by($request->ip()); // Adjust to 120
});
```

### 2. Request Validation ✅

All endpoints validate incoming requests:

- Required parameter checking
- Data type validation
- Prevention of SQL injection via Eloquent ORM

### 3. HTTPS Enforcement (Recommended)

**For Production, add to `app/Providers/AppServiceProvider.php`:**

```php
public function boot(): void
{
    if ($this->app->environment('production')) {
        \URL::forceScheme('https');
    }
}
```

## 🔒 Advanced Security Features

### 1. HMAC Signature Verification

Add request signature verification to prevent tampering.

**Update Controller:**

```php
// app/Http/Controllers/LicenseController.php

private function verifySignature(Request $request): bool
{
    $data = $request->key . $request->domain . $request->timestamp;
    $expectedSignature = hash_hmac('sha256', $data, config('app.license_secret'));
    
    return hash_equals($expectedSignature, $request->signature);
}

public function check(Request $request)
{
    // Validate signature
    if (!$this->verifySignature($request)) {
        return response()->json([
            'status' => 'invalid_signature',
            'msg' => 'Request signature is invalid'
        ], 401);
    }
    
    // Rest of the code...
}
```

**Add to `.env`:**

```env
LICENSE_SECRET=your-very-long-random-secret-key-here
```

**Client-side implementation:**

```php
$timestamp = time();
$signature = hash_hmac('sha256', $licenseKey . $domain . $timestamp, 'your-secret-key');

$url = "https://api.example.com/api/verify?" . http_build_query([
    'key' => $licenseKey,
    'domain' => $domain,
    'timestamp' => $timestamp,
    'signature' => $signature
]);
```

### 2. IP Address Lock

Prevent license from being used from different IPs.

**Add method to License model:**

```php
// app/Models/License.php

public function isIpAllowed(string $ip): bool
{
    // Allow if no IP is set yet
    if (empty($this->ip_address)) {
        return true;
    }
    
    return $this->ip_address === $ip;
}
```

**Update Controller:**

```php
// In LicenseController::check()

if (!$license->isIpAllowed($ip)) {
    return response()->json([
        'status' => 'invalid_ip',
        'msg' => 'IP address mismatch'
    ], 403);
}
```

### 3. Request Timestamp Validation

Prevent replay attacks by validating request timestamps.

**Add to Controller:**

```php
private function validateTimestamp($timestamp): bool
{
    $currentTime = time();
    $timeDifference = abs($currentTime - $timestamp);
    
    // Allow 5 minutes difference
    return $timeDifference <= 300;
}

public function check(Request $request)
{
    $timestamp = $request->input('timestamp');
    
    if (!$this->validateTimestamp($timestamp)) {
        return response()->json([
            'status' => 'invalid_timestamp',
            'msg' => 'Request timestamp is invalid or expired'
        ], 401);
    }
    
    // Rest of the code...
}
```

### 4. API Token Authentication

Add API token for additional security layer.

**Install Laravel Sanctum:**

```bash
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
```

**Add to routes:**

```php
// routes/api.php
Route::middleware(['auth:sanctum', 'throttle:api'])->group(function () {
    Route::get('/verify', [LicenseController::class, 'check']);
    Route::post('/activate', [LicenseController::class, 'activate']);
});
```

### 5. Encrypted License Keys

Store license keys encrypted in database.

**Update License Model:**

```php
// app/Models/License.php

use Illuminate\Support\Facades\Crypt;

protected $casts = [
    'expired_at' => 'date',
];

// Encrypt when setting
public function setLicenseKeyAttribute($value)
{
    $this->attributes['license_key'] = Crypt::encryptString($value);
}

// Decrypt when getting
public function getLicenseKeyAttribute($value)
{
    return Crypt::decryptString($value);
}
```

**Note:** This will require all existing license keys to be re-encrypted.

## 🚨 Security Checklist

### Before Going to Production

- [ ] Set `APP_DEBUG=false` in `.env`
- [ ] Set `APP_ENV=production` in `.env`
- [ ] Generate new `APP_KEY`: `php artisan key:generate`
- [ ] Enable HTTPS/SSL certificate
- [ ] Configure proper CORS settings
- [ ] Setup rate limiting appropriate for your use case
- [ ] Enable firewall rules
- [ ] Setup regular database backups
- [ ] Enable error logging
- [ ] Hide server version in headers
- [ ] Implement HMAC signature verification
- [ ] Add request timestamp validation
- [ ] Configure IP whitelisting (if applicable)
- [ ] Setup monitoring and alerts
- [ ] Regular security audits

## 🔥 Firewall Configuration

### Allow only necessary ports

```bash
# UFW (Ubuntu)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 22/tcp
sudo ufw enable
```

### Rate limit SSH

```bash
sudo ufw limit 22/tcp
```

## 📊 Security Monitoring

### 1. Log Failed Attempts

**Add to Controller:**

```php
use Illuminate\Support\Facades\Log;

if (!$license) {
    Log::warning('Invalid license attempt', [
        'key' => $key,
        'domain' => $domain,
        'ip' => $ip,
        'user_agent' => $request->userAgent()
    ]);
    
    return response()->json([
        'status' => 'invalid',
        'msg' => 'license key not found'
    ], 404);
}
```

### 2. Monitor Rate Limit Hits

```php
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;

RateLimiter::for('api', function (Request $request) {
    return Limit::perMinute(60)
        ->by($request->ip())
        ->response(function () use ($request) {
            Log::warning('Rate limit exceeded', [
                'ip' => $request->ip(),
                'endpoint' => $request->path()
            ]);
            
            return response()->json([
                'message' => 'Too many requests'
            ], 429);
        });
});
```

### 3. Install Laravel Telescope (Development Only)

```bash
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate
```

Access at: `http://your-domain.com/telescope`

## 🔐 Database Security

### 1. Use Prepared Statements

Laravel Eloquent already uses prepared statements. **Never use raw queries with user input:**

```php
// ❌ NEVER DO THIS
License::whereRaw("license_key = '$key'")->first();

// ✅ ALWAYS DO THIS
License::where('license_key', $key)->first();
```

### 2. Database User Permissions

Create a dedicated database user with limited permissions:

```sql
CREATE USER 'license_api'@'localhost' IDENTIFIED BY 'strong_password';
GRANT SELECT, INSERT, UPDATE ON license_server.* TO 'license_api'@'localhost';
FLUSH PRIVILEGES;
```

### 3. Enable MySQL SSL

Edit MySQL config:

```ini
[mysqld]
require_secure_transport=ON
ssl-ca=/path/to/ca.pem
ssl-cert=/path/to/server-cert.pem
ssl-key=/path/to/server-key.pem
```

## 🌐 CORS Configuration

**Install CORS package:**

```bash
composer require fruitcake/laravel-cors
```

**Configure `config/cors.php`:**

```php
return [
    'paths' => ['api/*'],
    'allowed_methods' => ['GET', 'POST'],
    'allowed_origins' => [
        'https://your-client-domain.com',
        'https://another-allowed-domain.com',
    ],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['Content-Type', 'X-Requested-With'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => false,
];
```

## 🔑 Environment Variables Security

### Never commit sensitive data

Add to `.gitignore`:

```
.env
.env.backup
.env.production
```

### Use different credentials per environment

```env
# Development
APP_KEY=base64:dev_key_here
DB_PASSWORD=dev_password

# Production
APP_KEY=base64:prod_key_here
DB_PASSWORD=strong_prod_password_here
```

## 🚀 Regular Maintenance

### Weekly Tasks

- Review error logs: `storage/logs/laravel.log`
- Check for failed login attempts
- Monitor disk space
- Review API usage patterns

### Monthly Tasks

- Update Laravel and dependencies: `composer update`
- Review and rotate API keys
- Database backup verification
- Security audit
- Check for Laravel security advisories

### Quarterly Tasks

- Penetration testing
- Review and update firewall rules
- SSL certificate renewal check
- Performance audit

## 📞 Incident Response

### If a security breach occurs:

1. **Immediately:**
   - Take the affected server offline
   - Change all passwords and API keys
   - Rotate `APP_KEY`: `php artisan key:generate`

2. **Investigation:**
   - Review logs in `storage/logs/`
   - Check database for unauthorized changes
   - Analyze access patterns

3. **Recovery:**
   - Restore from clean backup if needed
   - Apply security patches
   - Notify affected users

4. **Prevention:**
   - Document the incident
   - Update security measures
   - Implement additional monitoring

## 📚 Additional Resources

- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [Laravel Security Best Practices](https://laravel.com/docs/security)
- [PHP Security Guide](https://www.php.net/manual/en/security.php)

## ⚠️ Disclaimer

This guide provides security recommendations but does not guarantee complete protection. Security is an ongoing process that requires constant vigilance and updates.

---

**Last Updated:** 2025-11-23

**Remember:** Security is only as strong as its weakest link. Always stay updated with the latest security practices!

