cloudflare / cloudflare/cloudflared

access token: HEAD request to metadata endpoint times out with valid cached token (redirect follow bug)

Open
#1,637 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
Go
Stars
15.6k
Forks
1.4k
PR merge metrics
No merged PRs in 30d

Description

## Summary

`cloudflared access token ` times out on a metadata HEAD request even when a valid cached token exists in `~/.cloudflared/`. The same request succeeds instantly via `curl`.

## Version

```
cloudflared version 2026.3.0 (built 2026-03-06T12:53:40Z)
macOS Darwin 25.4.0 (arm64)
```

## Reproduction

```bash
# 1. Login successfully (token cached)
cloudflared access login https://my-app.example.com

# 2. Verify cached token exists and is valid
ls ~/.cloudflared/my-app.example.com-*-token

# 3. Try to retrieve the token — times out
cloudflared access token https://my-app.example.com
# Error: failed to get app info: Head "https://org.cloudflareaccess.com/cdn-cgi/access/login/my-app.example.com?kid=...&meta=&redirect_url=/": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
```

## Diagnosis

The failure is in the `get app info` step, which issues a **HEAD** request to:

```
https://.cloudflareaccess.com/cdn-cgi/access/login/?kid=&meta=&redirect_url=/
```

This endpoint returns a **302 redirect** to the protected origin (`https://my-app.example.com/`).

**Via curl (works):**
```bash
curl -s -o /dev/null -w "%{http_code} %{time_total}s" -I \
"https://org.cloudflareaccess.com/cdn-cgi/access/login/my-app.example.com?kid=...&redirect_url=%2F"
# 302 0.5s
```

**Via cloudflared (fails):**
Go's `net/http` client follows the 302 by default. The redirect target is the CF Access-protected origin, which either:
- Redirects back to the login endpoint (infinite loop), or
- Requires a valid CF Access token to respond (chicken-and-egg: we're calling `access token` to *get* the token)

This causes the internal timeout.

## Expected behavior

`cloudflared access token` should:
1. Check if a valid (non-expired) cached token exists in `~/.cloudflared/`
2. If valid, return it **without** making any network requests
3. Only hit the metadata endpoint when the token is expired or missing

The metadata HEAD should also use `CheckRedirect` to avoid following the 302, since the 302 itself confirms the app exists — the redirect target requires auth that the client doesn't have yet.

## Workaround

Read the cached token directly and validate the JWT `exp` claim:

```bash
TOKEN_FILE=$(find ~/.cloudflared -name "my-app.example.com-*-token" | head -1)
TOKEN=$(cat "$TOKEN_FILE")
# Validate exp claim before using
```

## Impact

This blocks all programmatic use of `cloudflared access token` when the metadata HEAD doesn't complete. Affects CI/CD pipelines, kubectl wrappers, and any automation that depends on `cloudflared access token` returning cached tokens reliably.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.