Implementing Consent Management for Third Parties

User consent for third-party data sharing requires granular controls and clear communication. Users should understand not just that data is shared, but with whom, for what purpose, and what specific data is involved. Consent interfaces must enable users to selectively approve or deny specific third-party integrations while maintaining core functionality where possible.

Technical implementation of third-party consent involves maintaining consent state, enforcing consent decisions at integration points, and providing users with ongoing visibility and control. This becomes complex when third parties have their own consent requirements or when integrations involve multiple purposes requiring separate consent.

// Third-party consent management system
class ThirdPartyConsentManager {
  constructor() {
    this.consentStore = new ConsentStore();
    this.integrationRegistry = new IntegrationRegistry();
    this.consentUI = new ConsentUIBuilder();
  }

  // Build granular consent interface for third parties
  buildConsentInterface(userId) {
    const integrations = this.integrationRegistry.getAll();
    const userConsents = this.consentStore.getUserConsents(userId);
    
    return {
      categories: this.groupIntegrationsByCategory(integrations),
      currentConsents: userConsents,
      interface: this.consentUI.build({
        style: 'granular',
        grouping: 'by-purpose',
        features: {
          selectAll: true,
          purposeDescriptions: true,
          dataPreview: true,
          vendorDetails: true
        }
      })
    };
  }

  // Process consent update with validation
  async updateConsent(userId, consentUpdate) {
    // Validate consent update
    const validation = this.validateConsentUpdate(consentUpdate);
    if (!validation.valid) {
      throw new Error(validation.error);
    }
    
    // Check for dependent consents
    const dependencies = this.checkConsentDependencies(consentUpdate);
    if (dependencies.hasConflicts) {
      return {
        success: false,
        conflicts: dependencies.conflicts,
        suggestions: dependencies.suggestions
      };
    }
    
    // Apply consent changes
    const result = await this.applyConsentChanges(userId, consentUpdate);
    
    // Update third parties
    await this.propagateConsentToVendors(userId, result.changes);
    
    // Update internal systems
    await this.updateInternalSystems(userId, result.changes);
    
    return result;
  }

  // Check and resolve consent dependencies
  checkConsentDependencies(consentUpdate) {
    const dependencies = {
      hasConflicts: false,
      conflicts: [],
      suggestions: []
    };
    
    // Check if disabling one integration affects others
    for (const [integrationId, consent] of Object.entries(consentUpdate)) {
      if (!consent) {
        const dependents = this.findDependentIntegrations(integrationId);
        if (dependents.length > 0) {
          dependencies.hasConflicts = true;
          dependencies.conflicts.push({
            integration: integrationId,
            dependents: dependents,
            reason: 'Other features depend on this integration'
          });
          dependencies.suggestions.push({
            action: 'disable_dependents',
            integrations: [integrationId, ...dependents]
          });
        }
      }
    }
    
    return dependencies;
  }

  // Propagate consent changes to vendors
  async propagateConsentToVendors(userId, changes) {
    const propagationResults = [];
    
    for (const change of changes) {
      const integration = this.integrationRegistry.get(change.integrationId);
      
      if (integration.supportsScopedConsent) {
        try {
          const result = await this.sendConsentUpdate(
            integration,
            userId,
            change
          );
          propagationResults.push({
            integrationId: change.integrationId,
            success: true,
            confirmationId: result.confirmationId
          });
        } catch (error) {
          propagationResults.push({
            integrationId: change.integrationId,
            success: false,
            error: error.message
          });
        }
      }
    }
    
    return propagationResults;
  }

  // Send consent update to specific vendor
  async sendConsentUpdate(integration, userId, change) {
    const consentPayload = {
      dataSubjectId: this.hashUserId(userId),
      consentStatus: change.newValue,
      purposes: change.purposes,
      timestamp: new Date().toISOString(),
      version: '2.0'
    };
    
    // Sign payload for integrity
    const signedPayload = await this.signPayload(consentPayload);
    
    // Send to vendor's consent endpoint
    const response = await fetch(integration.consentEndpoint, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${integration.apiKey}`,
        'X-Consent-Update': 'true'
      },
      body: JSON.stringify(signedPayload)
    });
    
    if (!response.ok) {
      throw new Error(`Vendor consent update failed: ${response.status}`);
    }
    
    return await response.json();
  }
}