Skip to main content

Tenant-Aware Security for SaaS and Platform Providers

·8 mins
cybersecurity cloudflare multitenancy multi tenancy tenants saas platform
Table of Contents

Modern SaaS and platform ecosystems rely on multi-tenant architectures – single infrastructures serving many distinct customers. This design maximizes scalability and efficiency but also centralizes risk: one vulnerability can impact all tenants. A tenant-based security strategy isolates risks, enforces per-customer policy, and maintains predictable control across layers of the stack.

This blueprint defines a practical Cloudflare-based approach to multitenant security strategy.

1. Foundational Layer: Account-Wide / Global Controls
#

All platforms begin with shared baseline controls. These global defenses must protect every tenant (user or customer) equally.

Recommended Controls:

  • Account-level WAF: Apply managed and custom rulesets at the account layer for consistent protection across all zones and domains.

Account-level WAF example

  • Global Rate Limiting: Mitigate volumetric or brute-force attacks at the edge before they reach origin.

Catch-All Origin Server Infrastructure Capacity Rate Limiting Rule

Gateway DNS Filtering Policy

These global measures define the shared defense surface, ensuring platform-wide protection regardless of tenant segmentation.

2. Tenant Isolation at Application Layer
#

SaaS applications vary widely in their exposure and tenant structure. Application layer controls must map individual requests to specific tenants to apply per-tenant policies (WAF, rate limits, logging). SaaS platforms commonly use one or more signals to identify tenants, such as: hostnames, metadata, JWT claims, headers (api-key), or values embedded in request bodies/payloads. Below are the most common patterns and their recommended implementations.

When No Tenant Identifier Exists
#

Example scenario: Tenants share a common endpoint (for example api.saas.com) and the request does not carry an explicit tenant ID. Therefore, identifiers must be set based on specific logic or derived dynamically.

Ideally, your application provides an explicit tenant identifier. If not, the long-term solution is to modify your application logic to introduce one. In the interim, you can use the following methods and approaches to derive or retrofit tenant identifiers:

  • Hostname Group Lists: Use host header (http.host)-based grouping to map specific hostnames to tenant tiers or categories. Use Cloudflare Lists to manage groups like free_tier_hostname_group, which may include hostnames like customer1.saas.com and customer2.saas.com.

  • Transform Rules: Inject or append tenant identifiers into query strings or response headers (e.g., add ?tenant=enterprise or X-Customer-Tier: enterprise), using supported filter expressions, so later rules can use them. Verify execution order with the phases list.

  • Rate limiting based on Header Value: Use the characteristics Header Value Of to apply throttling keyed to an API key (e.g. api-key) or tenant header.

  • Rate limiting using Response Headers: Increment counters based on response headers added by origin or backend logic (e.g., X-Tenant-ID: TenantID#1234) via the increment counter option.

These methods allow you to retrofit tenant signals into a shared endpoint without changing client URLs.

Vanity / Custom Hostnames as Tenant Identifier
#

Example scenario: Each tenant has a distinct hostname, vanity hostname or custom hostname (e.g., customer1.saas.com or saas.customer1.com). Related Case Study: Shopify.

When vanity domains or custom hostnames are in play, leverage Cloudflare for SaaS to attach Custom Metadata and use host headers as tenant signals:

  • Use the request host header http.host in WAF and Rate Limiting expressions.

Cloudflare for SaaS WAF Hostname

# Demo
curl https://customer2.cf-saas.com
  • Attach per-tenant Custom Metadata to custom hostnames and reference that metadata in security rules:

Cloudflare for SaaS WAF Custom Metadata

(http.user_agent contains "curl" and lookup_json_string(cf.hostname.metadata, "security_level") eq "low")
# Demo
curl https://customer1.cf-saas.com
lookup_json_string(cf.hostname.metadata, "tier") eq "enterprise"

Custom Metadata is evaluated before the WAF phase, making it suitable for attaching metadata consumed directly by security rules.

JWT-Based Controls
#

Example scenario: Shared API endpoint (api.saas.com) where requests carry JSON Web Tokens (JWTs) in Authorization: Bearer wyJhbGc..., which includes JWT claims from the JSON Web Keys (JWKs).

Use JWT validation and JWT claims for authentication, authorization, and per-tenant policy:

API JWT Validation Rule

# Demo
curl -I https://petstore.automatic-demo.com/api/v3/pet/findByStatus
  • Rate limiting by JWT claims: Enforce thresholds and quotas using custom JWT claims (e.g., tenant_id, user_tier claims).

Example JWT payload (Petstore serverless API for reference):

{
  "iss": "https://petstore.automatic-demo.com",
  "aud": "petstore",
  "sub": "user2",
  "exp": 1762698083,
  "iat": 1762697183,
  "username": "user2",
  "customer_type": "standard",
  "customer": {
    "username": "user2",
    "customer_type": "standard",
    "email": "user2@example.com",
    "company": null,
    "subscription_tier": null
  }
}

Advanced Rate Limiting JWT claim

WAF Custom Rules JWT claim

lookup_json_string(http.request.jwt.claims["<TOKEN_CONFIGURATION_ID>"][0], "customer_type") eq "standard"

For nested JSON values:

lookup_json_string(http.request.jwt.claims["<TOKEN_CONFIGURATION_ID>"][0], "customer", "username") == "user2"
  • Transform Rules: Forward selected JWT claims (e.g., tenant_id) as HTTP headers to the origin server for additional server-side validation, custom logic, or logging.

Request Header or API-Key Identification
#

Example scenario: Shared API endpoint (api.saas.com) where tenants are distinguished by request headers such as api-key, X-Tenant-ID, or X-User-ID.

Implementation notes:

  • Inspect request header fields to apply WAF and Rate Limiting selectively.

  • For per-tenant throttling, configure rate limiting with the Header Value Of characteristic using the api-key header so quotas are applied per API key.

Advanced Rate Limiting Header Value Of API-KEY

# Demo
for i in {1..400}; do
  curl -s -o /dev/null -w "%{http_code}\n" -H "api-key: something" -I "https://petstore.automatic-demo.com/api/v3/"
done

Request Payload / Body
#

Example scenario: Shared API endpoint (api.saas.com) where tenant identifier is carried inside request body JSON or form data (e.g. {"identifier":"TenantID#123", "data1":"content_here"}).

Use body- / payload-aware rules to extract tenant identifiers and make decisions at the edge:

lookup_json_string(http.request.body.raw, "identifier") eq "TenantID#123"

2.1 Tenant Isolation at Application Layer: Practical Summary Table
#

Tenant Identification PatternExample ScenarioCloudflare Implementation / Recommendation
No Tenant Identifier / DerivedShared endpoint (api.saas.com) with no built-in tenant IDModify Application Logic to embed tenant IDs; Hostname Group Lists; Transform Rules to inject headers/query strings; Rate Limiting by Header or Response Header
Vanity / Custom HostnamesTenant-specific hostnames (customer1.saas.com / saas.customer1.com)Cloudflare for SaaS Custom Metadata; http.host signals; tier-based WAF rules; per-tenant rate limits
JWT ClaimsShared API endpoint with Authorization: Bearer ... token containing tenant claimsAPI Shield JWT Validation; WAF rules using http.request.jwt.claims; Transform Rules to forward claims; Rate Limiting by JWT claim
Request Header / API KeyHeaders like api-key or X-Tenant-ID identify tenantsWAF selective rules on header fields; Rate Limiting using Header Value Of characteristic keyed to API key
Request Payload / BodyJSON or form data contains tenant identifiers (e.g., {"identifier":"TenantID#123"})lookup_json_string() on http.request.body.raw, http.request.body.form, or http.request.body.multipart for conditional WAF or rate limiting rules

3. Tenant-Level Observability
#

Security enforcement is only as effective as its visibility. Observe tenant-specific behavior to maintain isolation and accountability.

Observability must match enforcement granularity. Always verify execution order using the phases list.

4. Developer Platform (Customization)
#

Platform providers offering custom code execution environments for tenants must enforce strict sandboxing. Use Workers for Platforms (WfP) to isolate tenant workloads securely.

No tenant code executes without boundary isolation.

In terms of observability:

5. Security Framework Summary
#

LayerGoalCloudflare Mechanism
AccountShared baselineAccount-level WAF, Rate Limiting, Gateway DNS
ApplicationTenant differentiationMetadata, JWT, API Key, Headers, Tier Logic
ObservabilityTenant visibilityLogpush, Analytics, GraphQL
Developer PlatformTenant execution & storage isolationWorkers for Platforms, Rate Limit API, D1 SQLite, Durable Objects (DO)

Operational Checklist & Recommended Practices#

  • Map tenant-identifiers: decide which signal(s) will be canonical (host, metadata, JWT claim, header, body).
  • Apply account-level WAF & global rate limits as default deny/mitigation quotas.
  • Implement metadata for vanity hostnames using Cloudflare for SaaS where possible.
  • Validate JWTs at the edge, and extract tenant claims for rate limiting and logging.
  • Use Header Value Of for per-key rate limiting when APIs rely on API keys.
  • Use Transform Rules to normalize or inject tenant context when clients or application-logic cannot be changed.
  • Ensure logs and exported fields include tenant identifiers for SIEM correlation (Logpush custom fields).
  • Test rule execution order using the phases list.
  • For platforms exposing tenant code, enforce egress control, per-tenant rate limits, and ephemeral storage constraints.
  • Periodically drill incident simulations that measure detection, containment, and tenant notification flows.

Result
#

Tenant-aware security transforms Cloudflare’s global edge into an adaptive programmable enforcement and execution fabric: distributed, per-tenant isolated, and resilient. Shared infrastructure stays shared in design, not in exposure. The result is predictable, auditable tenant isolation with the operational controls needed for SaaS and platform providers.

Additional Options and Resources
#


Disclaimer
#

Educational purposes only.

This blog post is independently created and is not affiliated with, endorsed by, or necessarily representative of the views or opinions of any organizations or services mentioned herein.

The images used in this article primarily consist of screenshots from the Cloudflare Dashboard or other publicly available materials, such as Cloudflare webinar slides.

The author of this post is not responsible for any misconfigurations, errors, or unintended consequences that may arise from implementing the guidelines or recommendations discussed herein. You assume full responsibility for any actions taken based on this content and for ensuring that configurations are appropriate for your specific environment and use case.