cloudflare / cloudflare/cloudflared
access token: HEAD request to metadata endpoint times out with valid cached token (redirect follow bug)
- 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
Assessment
This issue has not been assessed yet.