simotion's avatar

Centralising SaaS management and securing communication with deployments

There’s a lot of information out there about building a SaaS, but guidance on managing multiple SaaS products in a centralized and scalable way seems scarce—or maybe I’m just not using the right search terms.

In preparation for the public launch of my first SaaS application, I’m building a central management platform which I'm naming 'MCP' -a slight nod to one of my all-time favorite movies, TRON- to manage deployments, accounts, subscriptions, and billing in a centralized and scalable way. Right now, I’m focusing on the architecture of the communication between the MCP and the deployments of my application(s).

Here’s a high-level overview of how I envisioned it to work:

  • Application servers only know which features are available and which limits apply per account.

  • Subscription plans, pricing, addons, and billing are managed centrally in the MCP.

  • When an account upgrades or purchases a subscription/addon, the MCP sends the new set of features and limits to the relevant deployment via signed API requests (HMAC/JWT).

  • The deployment server temporarily caches the payload and sends a SYN-ACK-like message back to confirm receipt. Only after receiving an ACK from the MCP are the new features applied to the account. The MCP only sends an ACK if it initiated the request.

  • FQDN-based communication:

    • Deployments know the MCP’s FQDN and direct all requests/responses there.

    • The MCP knows the main FQDN of each deployment; responses are always sent to this known FQDN.

    • Requests arriving via other FQDNs or IPs (e.g., through a CNAME) are accepted, but the sender in the request header is never used for the response.

    • Authenticity is ensured via the SYN-ACK/ACK handshake between verified URLs.

  • Server-to-server only: All communication between MCP and deployments happens directly between the backends. No client-side code ever communicates with the MCP.

The idea is that, even if a key or secret is intercepted, an unauthorized party cannot simply grant an account full access to all features.

💡 My questions for you:

  • How do you manage multiple SaaS products and deployments? Have you centralized it, and if so, what strategy did you use?

  • What strategies do you use to secure server-to-server communication between deployments?

  • Are there best practices for additional verification, key management, or secure feature provisioning that I might be missing in my approach?

0 likes
1 reply
LaryAI's avatar
Level 58

Absolutely! What you're building—a centralized Multi-SaaS Control Platform (MCP)—is a smart approach. Here are comprehensive answers and practical code strategies based on your architecture and questions:


1. Managing Multiple SaaS Products and Deployments

Centralization Strategy:

  • Central MCP acts as the "source of truth" for plans, subscriptions, entitlements, users, and payments.
  • Each Deployment acts as a satellite instance that only knows about enabled features/limits for its customers, ideally in a cached/temporary way.
  • Decoupling Deployments: Each deployment can operate independently but checks with MCP for “blessed” configuration and feature flags.
  • Sync Mechanism: Use an event-driven pattern where MCP sends signed payloads to the right deployment on any update.

Example structure:

[MCP]
  |
  |----> [App Deploy 1]
  |
  |----> [App Deploy 2]
  |
  |----> [App Deploy N]
  • Each deployment only stores the minimum info (feature set, limits, and user mapping).
  • Billing, payment, user identity, entitlements = always via MCP.

2. Securing Server-to-Server Communication

Best Practices:

  • Authentication: Use short-lived JWTs or HMAC signatures per request. Rotate keys periodically.
  • TLS Everywhere: Always use HTTPS, verify FQDNs, and pin certificates if feasible.
  • Whitelist FQDNs: All MCP <-> Deployment communication is only accepted from known domains.
  • Replay Protection: Include nonces and time-stamps in requests.
  • ACK/SYN-ACK Handshake: Prevents replay and fake payloads.

Sample Handshake Flow:

  1. MCP Initiates Update (SYN):

    • MCP sends a POST /api/feature-update to deployment including:
      • Signed JWT or HMAC
      • Nonce, Timestamp
      • Feature payload
  2. Deployment Responds (ACK):

    • Deployment processes, temporarily caches.
    • Sends a POST /api/feature-update/ack with:
      • Same Nonce, Reference ID
      • Signed response with deployment's own secret/key
  3. MCP Confirms (Final ACK if needed):

    • Optional: MCP sends a final confirmation.
    • Deployment applies changes only after this step.

Example: JWT Bearer Auth with Laravel

Generating a signed request from MCP:

// MCP signs the payload
$secret = env('DEPLOYMENT_SHARED_SECRET');
$payload = [
    'account_id' => 123,
    'features' => [...],
    'timestamp' => now()->timestamp,
    'nonce' => Str::random(32),
];

$jwt = JWT::encode($payload, $secret, 'HS256');

// MCP sends this with the HTTP request:
[
    'Authorization' => 'Bearer ' . $jwt,
    // ...other headers
]

Deployment verifies incoming request:

$jwt = $request->bearerToken();
$payload = JWT::decode($jwt, new Key($secret, 'HS256'));

// Validate timestamp, nonce, account ID, etc.
if (abs($payload->timestamp - now()->timestamp) > 30) { // 30 seconds clock skew
    abort(401, 'Stale request');
}

Non-Laravel Note:
You could also use tools like AWS App Mesh or HashiCorp Vault for extra service-to-service auth and secret management.


3. Key Management, Verification, Secure Feature Provisioning

Best Practices:

  • Short-lived tokens: Use JWTs or session keys with short valid durations and rolling expiry.
  • Key Rotation: Rotate shared secrets between MCP and all deployments at least quarterly, ideally automatically (see Vault, AWS KMS, or Azure Key Vault).
  • Audit Logging: Log every configuration or feature change event in both MCP and deployments. Log source IPs, IDs, JWT claim data.
  • Nonces & Replay Protection: Store recent nonces (last 1k) in Redis or DB to prevent replay attacks.
  • Layered Trust: Never let deployments "call home" to MCP and accept payloads directly; always have push-based model initiated through MCP.
  • FQDN Strictness: Never rely on sender info from headers; always respond to the registered deployment domain — as you described.
  • Feature Hash Validation: Compute a hash of the feature set, sign it, and send only signed hashes to the deployment; deployment only applies features if the hash is valid and acknowledged by MCP.

Example: Nonce + Hash + JWT

$features = [/* ... */];

// 1. MCP generates a canonical JSON blob
$featureJson = json_encode($features);

// 2. MCP creates hash and signs it
$featureHash = hash_hmac('sha256', $featureJson, $secret);
$jwt = JWT::encode([
    'feature_hash' => $featureHash,
    'timestamp' => now()->timestamp,
    'nonce' => Str::random(32),
], $secret, 'HS256');

// 3. Deployment verifies the hash and signature before applying

Summary Table

Best Practice Implementation
Centralized SaaS state & feature set MCP as source of truth, deployments cache feature flags temporarily
Server-to-server authentication Short-lived JWT/HMAC, signed with rotating secret
Secure channel Enforce HTTPS + domain pinning
Replay attack protection Nonces, timestamps, short-lived tokens
FQDN strictness Only respond to known deployment FQDN, never use sender headers
Key Management Rotate keys often, automate with secrets manager
Event Auditing & Logging Store all change and handshake events
"ACK-only" change application Deployments only update after MCP-issued ACK

Final Thoughts

Your handshake protocol plus mutual auth and centralized state is a strong pattern (see how Stripe, AWS, and others do it for inspiration). Make sure you test for timing attacks, replay, and network layer sniffing as well.

Let me know if you want code for a specific handshake endpoint or example Laravel code for both MCP and deployment sides!

Please or to participate in this conversation.