oauth2-proxy/oauth2-proxy · error

error making request to profile URL: %v

Error message

error making request to profile URL: %v

What it means

loadProfileClaims fetches the profile endpoint and unmarshals the response body as JSON via builder.UnmarshalSimpleJSON. When the response body is not parseable JSON (or the builder fails), this error is thrown — the message says 'error making request' but it fires on response decoding failures too.

Source

Thrown at pkg/providers/util/claim_extractor.go:117

		WithHeaders(c.requestHeaders).
		Do()

	// We first check if the result is a JWT token
	// https://openid.net/specs/openid-connect-core-1_0-final.html#UserInfoResponse
	mediaType, _, parseErr := mime.ParseMediaType(builder.Headers().Get("Content-Type"))

	if parseErr == nil && mediaType == "application/jwt" {
		// Decode and use JWT payload as profile claims
		if pl, err := parseJWT(string(builder.Body())); err == nil {
			return simplejson.NewJson(pl)
		}
	}

	// Otherwise, process as normal JSON payload
	claims, err := builder.UnmarshalSimpleJSON()

	if err != nil {
		return nil, fmt.Errorf("error making request to profile URL: %v", err)
	}

	return claims, nil
}

// GetClaimInto loads a claim and places it into the destination interface.
// This will attempt to coerce the claim into the specified type.
// If it cannot be coerced, an error may be returned.
func (c *claimExtractor) GetClaimInto(claim string, dst any) (bool, error) {
	value, exists, err := c.GetClaim(claim)
	if err != nil {
		return false, fmt.Errorf("could not get claim %q: %v", claim, err)
	}
	if !exists {
		return false, nil
	}
	if err := util.CoerceClaim(value, dst); err != nil {
		return false, fmt.Errorf("could not coerce claim: %v", err)

View on GitHub (pinned to 33c2eb92de)

Solutions

  1. Log/inspect the actual response body and status from the profile URL — it is likely HTML or empty, not JSON
  2. Confirm the request carries a valid access token so the endpoint returns JSON instead of an auth-redirect page
  3. Ensure request headers (Accept: application/json) and any proxy/gzip handling are correct
  4. Hit the endpoint with curl -H 'Authorization: Bearer <token>' to compare behavior

Example fix

// before: no auth header on profile request
headers := http.Header{}

// after: pass the access token so the endpoint returns JSON claims
headers := http.Header{}
headers.Set("Authorization", "Bearer "+accessToken)
extractor, _ := util.NewClaimExtractor(ctx, idToken, profileURL, headers)
Defensive patterns

Strategy: try-catch

Validate before calling

resp, err := client.Get(profileURL.String())
if err != nil { return err }
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK || !json.Valid(body) {
    return fmt.Errorf("profile endpoint returned non-JSON (status %d)", resp.StatusCode)
}

Try / catch

claims, err := c.loadProfileClaims()
if err != nil {
    return nil, fmt.Errorf("error making request to profile URL: %v", err)
}

Prevention

When it happens

Trigger: GetClaim -> loadProfileClaims where the profile endpoint returned a body that cannot be unmarshaled into a simplejson object — e.g. an HTML error page, empty body, or gzip/encoding mismatch.

Common situations: IdP returning an HTML login/error page instead of JSON (auth redirect not followed), reverse proxy serving an error page, wrong Content-Type, or a captive portal intercepting the request.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of oauth2-proxy/oauth2-proxy@33c2eb92de (2026-09-06). Data as JSON: /api/errors/d4eeba8f4b082446. Report an issue: GitHub.