Back to Blog
Lesson 31 of the Cloudflare: Cloudflare for Developers: DNS to CDN course
Cloud NativeAugust 9, 20264 min read

Project Milestone: Securing the Full Stack with Cloudflare

Secure your R2 and D1 application by enforcing authentication, applying custom WAF rules, and verifying end-to-end data flow in this hands-on project milestone.

SecurityWAFWorkersAuthenticationFullstackCloudflare
A laptop displaying code editor with a motivational mug that reads 'Make It Happen' on a workspace.

Previously in this course, we covered Authentication Fundamentals: Securing Your Cloudflare Workers API and implemented WAF Custom Rules: Securing Apps with Cloudflare Traffic Control. This lesson brings everything together by applying these security layers to your Project Milestone: The Dynamic Backend | Cloudflare for Developers infrastructure.

Securing the Full Stack: A Defense-in-Depth Approach

Security isn't a single checkbox; it's a stack of filters. In a serverless architecture using Workers, D1, and R2, your goal is to ensure that only authorized users reach your database, and that your endpoints are protected from automated abuse.

We will implement a three-tiered security strategy:

  1. Edge-Level WAF: Filtering malicious traffic before it hits your Worker code.
  2. Identity-Aware Routes: Enforcing authentication within your Worker before executing D1 or R2 operations.
  3. Data Integrity: Ensuring that the flow between R2 assets and D1 metadata is validated.

Tier 1: Enforcing WAF Rules for Sensitive Endpoints

A fenced gate displaying a "No Dogs Allowed" sign with graffiti in a park setting.

Before our code even executes, we want to block common attack vectors. Since our API handles administrative tasks (like uploading files to R2 or updating D1 metadata), we need to ensure these sensitive paths are protected by the WAF.

Navigate to the Cloudflare Dashboard under Security > WAF > Custom Rules. Create a rule to protect your /api/admin/* path:

  • Rule Name: Protect Admin API
  • Expression: (http.request.uri.path contains "/api/admin") and (ip.geoip.country ne "US")
  • Action: Block

This ensures that only traffic originating from your trusted geographic region can attempt to access administrative API routes.

Tier 2: Enforcing Authentication on API Routes

With the WAF filtering general traffic, we must now gate the actual execution inside our Worker. We will use the authentication logic we built previously to guard our D1/R2 operations.

Worked Example: Authenticated API Middleware

Modify your primary index.js or worker.js file to include a middleware check. This ensures any route starting with /api/data requires a valid authorization header.

JAVASCRIPT
export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    // Protect all API data routes
    if (url.pathname.startsWith(CE9178">'/api/data')) {
      const authHeader = request.headers.get(CE9178">'Authorization');
      
      // Validate against your secret stored via CE9178">`wrangler secret`
      if (authHeader !== env.API_TOKEN) {
        return new Response(CE9178">'Unauthorized', { status: 401 });
      }
    }

    // Proceed to handle R2/D1 logic
    return handleRequest(request, env);
  }
};

By checking the env.API_TOKEN (which you set using wrangler secret put API_TOKEN), you create a hard stop for unauthorized traffic before the Worker touches your D1 database or R2 bucket.

Tier 3: Verifying Secure Data Flow

The final step is verifying that our data flow remains secure. Since we are serving R2 assets based on D1 metadata, ensure your Worker does not expose internal file paths.

Hands-on Exercise: Audit Your Flow

  1. Test the Gatekeeper: Attempt a curl request to your protected endpoint without the Authorization header: curl -I https://your-domain.com/api/data/files Expectation: 401 Unauthorized.
  2. Test the WAF: Attempt a request from a blocked region (or change the WAF rule to block your current IP temporarily): Expectation: 403 Forbidden.
  3. Verify Header Stripping: Ensure your Worker is not leaking x-amz-request-id or other backend-specific headers from R2 by explicitly setting only the headers you want to return in your response object.

Common Pitfalls

Close-up of a triangular warning sign indicating a slippery surface, fixed to a wooden post.

  • Hardcoding Secrets: Never include your API_TOKEN in your source code. Always use Managing Secrets Securely: A Cloudflare Workers Guide to inject these values at runtime.
  • Over-blocking: When applying WAF rules, start with "Log" mode before switching to "Block" to ensure you aren't accidentally dropping legitimate traffic.
  • Ignoring CORS: If your frontend is on a different domain, your authenticated API calls will fail due to CORS preflight requests. Always handle OPTIONS requests in your middleware.

FAQ

Q: Can I use Cloudflare Access instead of custom header auth? A: Yes, Cloudflare Access is excellent for team-based security. However, for public-facing APIs, manual header validation or JWT verification is typically the standard.

Q: Does the WAF rule impact performance? A: No, Cloudflare's WAF runs at the edge and is optimized to evaluate rules in microseconds, adding negligible latency.

Recap

Team members presenting a project in a modern office setting with a focus on collaboration.

You have now secured your full-stack application by combining edge-level WAF filtering, Worker-based authentication, and careful header management. Your R2 and D1 resources are no longer exposed to the open internet, and your API is protected against unauthorized access.

Up next: Workers Routes and Custom Domains — we'll map your secured Worker to a clean, professional subdomain for your final production release.

Similar Posts