cloudflare/cloudflared · error
failed to parse auth_domain %q: %w
Error message
failed to parse auth_domain %q: %w
What it means
parseAuthDomain in token/jwks.go normalizes the auth_domain claim from the Cloudflare Access metadata JWT into an https URL used for JWKS fetches and cache paths. The claim is prefixed with "https://" and parsed with url.Parse; if that parse fails (malformed input, control characters, invalid URL syntax) the error is wrapped as "failed to parse auth_domain %q: %w".
Source
Thrown at token/jwks.go:84
payload, err := jws.Verify(keySet)
if err != nil {
return nil, errors.Wrap(err, "failed to verify metadata JWT signature")
}
var claims metadataClaims
if err := json.Unmarshal(payload, &claims); err != nil {
return nil, errors.Wrap(err, "failed to decode verified metadata JWT claims")
}
return &claims, nil
}
// parseAuthDomain extracts the canonical hostname used for JWKS requests and
// cache paths from the auth_domain claim.
func parseAuthDomain(authDomain string) (url.URL, error) {
parsed, err := url.Parse(httpsScheme + "://" + authDomain)
if err != nil {
return url.URL{}, fmt.Errorf("failed to parse auth_domain %q: %w", authDomain, err)
}
hostname := strings.ToLower(parsed.Hostname())
if !strings.HasSuffix(hostname, accessDomainSuffix) {
return url.URL{}, fmt.Errorf("auth_domain %q does not end with %q", authDomain, accessDomainSuffix)
}
return url.URL{Scheme: httpsScheme, Host: hostname}, nil
}
// fetchJWKS fetches the JWKS from the auth domain's certs endpoint over HTTPS.
func fetchJWKS(authDomain url.URL) (*jose.JSONWebKeySet, error) {
jwksURL := authDomain
jwksURL.Path = accessCertPath
client := &http.Client{
CheckRedirect: func(_ *http.Request, _ []*http.Request) error {
return http.ErrUseLastResponse
},
Timeout: time.Second * 10,View on GitHub (pinned to 2253eeeb25)
Solutions
- Check the auth_domain value being passed: it should be a bare hostname like "myteam.cloudflareaccess.com" — no scheme, path, spaces, or wildcards.
- Re-fetch the Access metadata JWT; if it came from a stale/corrupted cache or token, obtain a fresh tunnel token from the Cloudflare dashboard.
- Fix the TUNNEL_TOKEN / Access application configuration in the Cloudflare Zero Trust dashboard so the team domain is a valid hostname.
- Validate the team domain string before constructing the token/config (reject empty or non-hostname values).
Example fix
// before — full URL pasted as team domain authDomain := "https://myteam.cloudflareaccess.com/" // url.Parse still succeeds here, but e.g. "my team" fails // after — bare hostname only authDomain := "myteam.cloudflareaccess.com" url, err := parseAuthDomain(authDomain)
Defensive patterns
Strategy: validation
Validate before calling
func validAuthDomainInput(authDomain string) error {
if authDomain == "" {
return errors.New("auth_domain is empty")
}
if strings.ContainsAny(authDomain, " \t\r\n/") {
return fmt.Errorf("auth_domain %q must be a bare hostname", authDomain)
}
if _, err := url.Parse("https://" + authDomain); err != nil {
return fmt.Errorf("auth_domain %q is not a valid URL: %w", authDomain, err)
}
return nil
} Type guard
func looksLikeHostname(s string) bool {
u, err := url.Parse("https://" + s)
return err == nil && u.Hostname() != "" && !strings.ContainsAny(s, " /\t\n")
} Try / catch
ad, err := parseAuthDomain(authDomain)
var uerr *url.Error
if err != nil {
if errors.As(err, &uerr) {
log.Error().Err(uerr).Str("authDomain", authDomain).Msg("malformed auth_domain claim; re-issue tunnel token")
}
return err
} Prevention
- Never hand-edit tunnel tokens; download them fresh from the Zero Trust dashboard.
- Store the team domain as a bare hostname without scheme or trailing slash.
- Validate team-name inputs for whitespace/URL-unsafe characters before building tokens.
When it happens
Trigger: GetAppInfo / testAuthDomain / metadata decoding pass an auth_domain string whose "https://" + authDomain cannot be parsed by net/url.Parse — e.g. the claim contains spaces, control characters, or malformed percent-encodings, or is empty in a way that produces an invalid URL.
Common situations: A corrupted or tampered metadata JWT yields a bogus auth_domain claim; a misconfigured Access application sets auth_domain to a full URL ("https://team.cloudflareaccess.com") or with a scheme/path embedded oddly; environment variables (TUNNEL_TOKEN-based flows) contain a manually edited team name with whitespace or URL-unsafe characters.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- invalid token
- metadata JWT aud is empty
- metadata JWT iat is missing or invalid
- auth_domain %q does not end with %q
- metadata JWT auth_domain validation failed: %w
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/4cee407c9c4295ee.
Report an issue: GitHub.