Rahul Reddy

I build AI platforms, Cross-Platform Apps, and the Infra they run on.

Building in the open, writing about what breaks, and sharing the occasional opinion.

hi [at] rahulmx.com
GoTypeScriptSwiftPythoniOSSwiftUIReact NativeNext.jsReactNode.jsFastAPILLM OrchestrationAgentic SystemsLiteLLMRAGPrompt EngineeringPostgreSQLBigQuerySnowflakeRedisMongoDBGCPDockerTerraformProxmoxGitHub ActionsCloudflare WorkersCloudflare R2Cloudflare D1Cloudflare TunnelDistributed SystemsAPI DesignData PipelinesPlatform ArchitectureGoTypeScriptSwiftPythoniOSSwiftUIReact NativeNext.jsReactNode.jsFastAPILLM OrchestrationAgentic SystemsLiteLLMRAGPrompt EngineeringPostgreSQLBigQuerySnowflakeRedisMongoDBGCPDockerTerraformProxmoxGitHub ActionsCloudflare WorkersCloudflare R2Cloudflare D1Cloudflare TunnelDistributed SystemsAPI DesignData PipelinesPlatform Architecture

CloudflareAccessTerraform

Cloudflare Access: use decision=non_identity for service-to-service auth

decision = "non_identity"

service_token = [token.id]

The default decision = "allow" policy redirects unauthenticated requests to a login page - which breaks any service or script hitting the endpoint programmatically. The fix is a separate policy with decision = "non_identity" that matches on a service token.

Terraform setup

Create a service token and an Access policy that allows it through without triggering an identity flow:

resource "cloudflare_zero_trust_access_service_token" "api_client" {
  account_id           = var.cloudflare_account_id
  name                 = "aigw-client"
  min_days_for_renewal = 30
}

resource "cloudflare_zero_trust_access_policy" "api_service_token" {
  account_id     = var.cloudflare_account_id
  application_id = cloudflare_zero_trust_access_application.api.id
  name           = "Service Token"
  precedence     = 1
  decision       = "non_identity"

  include {
    service_token = [cloudflare_zero_trust_access_service_token.api_client.id]
  }
}

Set precedence = 1 so the service token policy is evaluated before any email/identity policy.

Also set skip_interstitial = true on the application to suppress the Access login page for matched requests:

resource "cloudflare_zero_trust_access_application" "api" {
  ...
  skip_interstitial = true
}

Request headers

The calling service must send the two values output by the service token resource:

CF-Access-Client-Id: <client_id output>
CF-Access-Client-Secret: <client_secret output>

If the token matches the policy the request passes through. If not, Cloudflare returns a 403.