Skip to content

Authentication

Splinterpic uses IP whitelisting to secure API access. This approach is ideal for edge deployments where you control the infrastructure making requests.

Every request to your Splinterpic Worker is checked against an IP whitelist before any processing occurs. If the requesting IP isn’t on the whitelist, the request is immediately rejected with a 403 Forbidden response.

┌──────────┐ ┌─────────────────┐ ┌──────────┐
│ Client │────────▶│ Worker (Edge) │────────▶│ Database │
└──────────┘ └─────────────────┘ └──────────┘
┌─────────────────┐
│ IP Whitelist │
│ Check (FIRST) │
└─────────────────┘
✓ Allow / ✗ Deny

First, determine which IP addresses need access. Common scenarios:

Development Machine:

Terminal window
curl https://api.ipify.org

Cloudflare Pages (for frontend): Cloudflare Pages requests come from Cloudflare’s edge network. Check request headers for CF-Connecting-IP.

Your Server:

Terminal window
curl -4 ifconfig.me

###Step 2: Update wrangler.toml

Open your wrangler.toml file and add allowed IPs to the ALLOWED_IPS variable:

[vars]
ALLOWED_IPS = "203.0.113.1,198.51.100.42,192.0.2.100"

After updating wrangler.toml, redeploy your Worker:

Terminal window
npm run worker:deploy

Changes take effect immediately across Cloudflare’s global network.

[vars]
ALLOWED_IPS = "203.0.113.1"
[vars]
ALLOWED_IPS = "203.0.113.1,198.51.100.42,192.0.2.100"
[vars]
# Local development IP + production server IP
ALLOWED_IPS = "127.0.0.1,203.0.113.1"

The IP whitelist check is performed in worker/index.ts:

function checkIPWhitelist(request: Request, env: Env): boolean {
const clientIP = request.headers.get('CF-Connecting-IP');
if (!clientIP) {
return false;
}
const allowedIPs = env.ALLOWED_IPS.split(',').map(ip => ip.trim());
return allowedIPs.includes(clientIP);
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// IP check happens FIRST, before any other processing
if (!checkIPWhitelist(request, env)) {
return new Response('Forbidden', { status: 403 });
}
// ... rest of request handling
}
}

Only whitelist IPs that absolutely need access:

# ❌ Bad: Overly permissive
ALLOWED_IPS = "0.0.0.0"
# ✅ Good: Specific IPs only
ALLOWED_IPS = "203.0.113.1,198.51.100.42"

Review your IP whitelist monthly:

Terminal window
# View current whitelist
grep ALLOWED_IPS wrangler.toml

Remove IPs that are no longer needed.

Use environment-specific configurations:

wrangler.toml (production):

[vars]
ALLOWED_IPS = "203.0.113.1"

wrangler.dev.toml (development - optional):

[vars]
ALLOWED_IPS = "127.0.0.1,::1"

Add logging to track unauthorized access attempts:

if (!checkIPWhitelist(request, env)) {
console.warn(`Unauthorized access attempt from: ${clientIP}`);
return new Response('Forbidden', { status: 403 });
}
Terminal window
# Should succeed (200 OK)
curl -i https://your-worker.workers.dev/api/models

Use a proxy or VPN to test from a non-whitelisted IP:

Terminal window
# Should fail (403 Forbidden)
curl -i https://your-worker.workers.dev/api/models

Expected response:

HTTP/2 403
Forbidden

Cause: Your current IP isn’t in the whitelist.

Solution:

  1. Find your IP: curl https://api.ipify.org
  2. Add to wrangler.toml: ALLOWED_IPS = "your.ip.here"
  3. Redeploy: npm run worker:deploy

Requests Work Locally But Not in Production

Section titled “Requests Work Locally But Not in Production”

Cause: Your production server has a different IP than your development machine.

Solution: Add both IPs to the whitelist:

[vars]
ALLOWED_IPS = "dev.ip.address,prod.ip.address"

Cause: Your ISP assigns dynamic IPs that change periodically.

Solution: Consider these options:

  1. Use a VPN with a static IP
  2. Deploy a proxy server with a static IP
  3. Use Cloudflare Access for more advanced auth
  4. Migrate to API key authentication (requires code changes)

If IP whitelisting doesn’t fit your use case, you can implement API key authentication. Here’s a basic example:

worker/index.ts
function checkAPIKey(request: Request, env: Env): boolean {
const apiKey = request.headers.get('Authorization')?.replace('Bearer ', '');
if (!apiKey) {
return false;
}
// Store API keys in Cloudflare KV or D1
return apiKey === env.API_KEY;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (!checkAPIKey(request, env)) {
return new Response('Unauthorized', { status: 401 });
}
// ... rest of request handling
}
}

Then set your API key in wrangler.toml:

[vars]
API_KEY = "your-secret-api-key-here"

All authentication configuration happens through environment variables in wrangler.toml:

VariableTypeDescription
ALLOWED_IPSstringComma-separated list of allowed IP addresses
  • Deploy to Production - Learn production deployment best practices Deploy →
  • API Reference - Explore authenticated API endpoints View docs →
  • Environment Variables - Configure all Worker environment variables Setup →

Questions about authentication?