oauth2-proxy/oauth2-proxy · error

unable to unmarshal raw response body: %w

Error message

unable to unmarshal raw response body: %w

What it means

fetchToken parses the token endpoint's HTTP response body. It first unmarshals the body into a generic interface to keep the raw response (for oauth2 token extras). This error is thrown when the body is not valid JSON, wrapping the json.Unmarshal error.

Source

Thrown at providers/ms_entra_id.go:318

		}
	}
	return false
}

func (p *MicrosoftEntraIDProvider) fetchToken(ctx context.Context, params url.Values) (*oauth2.Token, error) {
	resp := requests.New(p.RedeemURL.String()).
		WithContext(ctx).
		WithMethod(http.MethodPost).
		WithBody(bytes.NewBufferString(params.Encode())).
		SetHeader("Content-Type", "application/x-www-form-urlencoded").
		Do()

	var token *oauth2.Token
	var rawResponse interface{}

	body := resp.Body()
	if err := json.Unmarshal(body, &rawResponse); err != nil {
		return nil, fmt.Errorf("unable to unmarshal raw response body: %w", err)
	}

	if err := json.Unmarshal(body, &token); err != nil {
		return nil, fmt.Errorf("unable to unmarshal token response body: %w", err)
	}

	return token.WithExtra(rawResponse), nil
}

View on GitHub (pinned to 33c2eb92de)

Solutions

  1. Log the actual response body (the wrapped %w error includes the JSON syntax detail) to see what came back
  2. Check for a corporate proxy/WAF intercepting requests to login.microsoftonline.com and add an exception
  3. Verify the configured token endpoint URL points at the real OAuth2 token endpoint
  4. Retry — transient gateway errors can return truncated/empty bodies
Defensive patterns

Strategy: retry

Validate before calling

// preflight: check connectivity through your proxy to the token endpoint
req, _ := http.NewRequest("POST", tokenURL, nil)
resp, err := http.DefaultClient.Do(req)
if err == nil && strings.Contains(http.DetectContentType(peerBody(resp)), "text/html") {
    log.Println("proxy/WAF returned HTML instead of JSON")
}

Try / catch

if err := provider.RefreshSession(ctx, sess); err != nil {
    if strings.Contains(err.Error(), "unable to unmarshal raw response body") {
        // body wasn't JSON (proxy page, empty body): retry after backoff, then alert
    }
}

Prevention

When it happens

Trigger: fetchToken (called from redeemWithFederatedToken / redeemRefreshTokenWithFederatedToken) receives a response body that is not valid JSON: HTML error pages from proxies/gateways, empty bodies, or plain-text errors from Azure AD or an intercepting middlebox.

Common situations: Corporate proxy or WAF returning an HTML block page; Azure AD returning a non-JSON error; wrong token endpoint URL hitting a login page; TLS-terminating appliance injecting content.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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