226 lines
6.9 KiB
Markdown
226 lines
6.9 KiB
Markdown
# Salesforce-to-Portal Security Integration Guide
|
|
|
|
Note: 2025 update — Salesforce → Portal order provisioning is now event-driven via Platform Events. This document reflects the event-driven model.
|
|
|
|
## Overview
|
|
|
|
This guide outlines secure patterns for **Salesforce-to-Portal communication** specifically for the **order provisioning workflow**. Based on your architecture, this focuses on order status updates, not invoice handling.
|
|
|
|
## Order Provisioning Flow (Async Preferred)
|
|
|
|
```
|
|
Portal Customer → Places Order → Salesforce Order (Pending Review)
|
|
↓
|
|
Salesforce Operator → Reviews/Approves Order
|
|
↓
|
|
Salesforce Flow → Publishes OrderProvisionRequested__e
|
|
↓
|
|
Portal BFF Subscriber → Provisions in WHMCS → Updates Salesforce Order Status
|
|
↓
|
|
Portal → Polls Order Status → Shows Customer Updates
|
|
```
|
|
|
|
## 1. Secure Order Provisioning Communication
|
|
|
|
### Primary Method: Platform Events (Recommended)
|
|
|
|
Use a Record-Triggered Flow to publish `OrderProvisionRequested__e`. The portal subscribes via the Salesforce Streaming API (Pub/Sub) and provisions asynchronously. Inbound webhooks from Salesforce are no longer required.
|
|
|
|
If you still need synchronous HTTP for another use case, prefer OAuth2 Named/External Credential and avoid custom signature schemes.
|
|
|
|
### Secure Salesforce Quick Action Setup (Legacy)
|
|
|
|
Legacy Quick Action + webhook details removed (use Platform Events).
|
|
|
|
2. **Apex Class for Secure Webhook Calls**
|
|
// Your current pattern in salesforce-connection.service.ts
|
|
// Uses private key JWT authentication - industry standard
|
|
|
|
````
|
|
|
|
### Enhanced Patterns for Sensitive Operations
|
|
|
|
For highly sensitive operations, consider adding:
|
|
|
|
```typescript
|
|
@Injectable()
|
|
export class SecureSalesforceService {
|
|
async createSensitiveRecord(data: SensitiveData, idempotencyKey: string) {
|
|
// 1. Encrypt sensitive fields before sending
|
|
const encryptedData = this.encryptSensitiveFields(data);
|
|
|
|
// 2. Add idempotency protection
|
|
const headers = {
|
|
'Idempotency-Key': idempotencyKey,
|
|
'X-Request-ID': uuidv4(),
|
|
};
|
|
|
|
// 3. Use your existing secure connection
|
|
return await this.salesforceConnection.create(encryptedData, headers);
|
|
}
|
|
|
|
private encryptSensitiveFields(data: any): any {
|
|
// Encrypt PII fields before transmission
|
|
const sensitiveFields = ['ssn', 'creditCard', 'personalId'];
|
|
// Implementation depends on your encryption strategy
|
|
}
|
|
}
|
|
````
|
|
|
|
## 3. Data Protection Guidelines
|
|
|
|
### Sensitive Data Handling
|
|
|
|
```typescript
|
|
// Example: Secure order processing
|
|
export class SecureOrderService {
|
|
async processOrderApproval(orderData: OrderApprovalData) {
|
|
// 1. Validate customer permissions
|
|
await this.validateCustomerAccess(orderData.customerNumber);
|
|
|
|
// 2. Sanitize data for logging
|
|
const sanitizedData = this.sanitizeForLogging(orderData);
|
|
this.logger.log("Processing order approval", sanitizedData);
|
|
|
|
// 3. Process with minimal data exposure
|
|
const result = await this.processOrder(orderData);
|
|
|
|
// 4. Audit trail without sensitive data
|
|
await this.createAuditLog({
|
|
action: "order_approved",
|
|
customerNumber: orderData.customerNumber,
|
|
orderId: orderData.orderId,
|
|
timestamp: new Date(),
|
|
// No sensitive payment or personal data
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
private sanitizeForLogging(data: any): any {
|
|
// Remove or mask sensitive fields for logging
|
|
const { creditCard, ssn, ...safeData } = data;
|
|
return {
|
|
...safeData,
|
|
creditCard: creditCard ? "****" + creditCard.slice(-4) : undefined,
|
|
ssn: ssn ? "***-**-" + ssn.slice(-4) : undefined,
|
|
};
|
|
}
|
|
}
|
|
```
|
|
|
|
### Field-Level Security
|
|
|
|
```typescript
|
|
// Implement field-level encryption for highly sensitive data
|
|
export class FieldEncryptionService {
|
|
private readonly algorithm = "aes-256-gcm";
|
|
private readonly keyDerivation = "pbkdf2";
|
|
|
|
async encryptField(value: string, fieldType: string): Promise<EncryptedField> {
|
|
const key = await this.deriveKey(fieldType);
|
|
const iv = crypto.randomBytes(16);
|
|
const cipher = crypto.createCipher(this.algorithm, key);
|
|
|
|
let encrypted = cipher.update(value, "utf8", "hex");
|
|
encrypted += cipher.final("hex");
|
|
|
|
return {
|
|
value: encrypted,
|
|
iv: iv.toString("hex"),
|
|
tag: cipher.getAuthTag().toString("hex"),
|
|
};
|
|
}
|
|
|
|
async decryptField(encryptedField: EncryptedField, fieldType: string): Promise<string> {
|
|
const key = await this.deriveKey(fieldType);
|
|
const decipher = crypto.createDecipher(this.algorithm, key);
|
|
|
|
decipher.setAuthTag(Buffer.from(encryptedField.tag, "hex"));
|
|
|
|
let decrypted = decipher.update(encryptedField.value, "hex", "utf8");
|
|
decrypted += decipher.final("utf8");
|
|
|
|
return decrypted;
|
|
}
|
|
}
|
|
```
|
|
|
|
## 4. Implementation Checklist
|
|
|
|
### Salesforce Setup
|
|
|
|
- [ ] Create Platform Events for portal notifications
|
|
- [ ] Configure IP allowlisting for portal endpoints
|
|
- [ ] Create audit trails for all portal communications
|
|
|
|
### Portal Setup
|
|
|
|
- [ ] Add IP allowlisting for Salesforce
|
|
- [ ] Create encrypted payload handling
|
|
- [ ] Implement idempotency protection
|
|
|
|
### Security Measures
|
|
|
|
- [ ] Implement rate limiting per customer
|
|
- [ ] Add comprehensive audit logging
|
|
- [ ] Test disaster recovery procedures
|
|
|
|
## 5. Monitoring and Alerting
|
|
|
|
```typescript
|
|
@Injectable()
|
|
export class SecurityMonitoringService {
|
|
async monitorWebhookSecurity(request: Request, response: any) {
|
|
const metrics = {
|
|
sourceIp: request.ip,
|
|
userAgent: request.headers["user-agent"],
|
|
timestamp: new Date(),
|
|
success: response.success,
|
|
processingTime: response.processingTime,
|
|
};
|
|
|
|
// Alert on suspicious patterns
|
|
if (this.detectSuspiciousActivity(metrics)) {
|
|
await this.sendSecurityAlert(metrics);
|
|
}
|
|
|
|
// Log for audit
|
|
this.logger.log("Webhook security metrics", metrics);
|
|
}
|
|
|
|
private detectSuspiciousActivity(metrics: any): boolean {
|
|
// Implement your security detection logic
|
|
// - Too many requests from same IP
|
|
// - Unusual timing patterns
|
|
// - Failed authentication attempts
|
|
return false;
|
|
}
|
|
}
|
|
```
|
|
|
|
## 7. Production Deployment
|
|
|
|
### Environment Variables
|
|
|
|
```bash
|
|
# Platform Events
|
|
SF_EVENTS_ENABLED=true
|
|
SF_PROVISION_EVENT_CHANNEL=/event/OrderProvisionRequested__e
|
|
SF_EVENTS_REPLAY=LATEST
|
|
|
|
# Encryption
|
|
FIELD_ENCRYPTION_KEY=your_field_encryption_master_key
|
|
ENCRYPTION_KEY_ROTATION_DAYS=90
|
|
|
|
# Monitoring
|
|
SECURITY_ALERT_WEBHOOK=https://your-monitoring-service.com/alerts
|
|
AUDIT_LOG_RETENTION_DAYS=2555 # 7 years for compliance
|
|
```
|
|
|
|
### Salesforce Named Credential Setup
|
|
|
|
Not required for the event-driven provisioning path (the portal pulls events).
|
|
|
|
This guide provides a comprehensive, production-ready approach to secure Salesforce-Portal integration that builds on your existing security infrastructure while adding enterprise-grade protection for sensitive data transmission.
|