oauth2-proxy/oauth2-proxy · error

error fetching token: %w

Error message

error fetching token: %w

What it means

After assembling the authorization-code exchange parameters (client_assertion_type jwt-bearer, code, grant_type), redeemWithFederatedToken calls fetchToken to POST to the Entra token endpoint. Any failure there — network error, non-2xx response, or unparsable token response — is wrapped as 'error fetching token: %w' (note the %w, so errors.Is/As unwrapping works).

Source

Thrown at providers/ms_entra_id.go:136

	}

	params := url.Values{}

	// Exchange parameters for token federation
	// https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#request-an-access-token-with-a-certificate-credential
	if codeVerifier != "" {
		params.Add("code_verifier", codeVerifier)
	}
	params.Add("redirect_uri", redirectURL)
	params.Add("client_id", p.ClientID)
	params.Add("client_assertion", string(federatedToken))
	params.Add("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
	params.Add("code", code)
	params.Add("grant_type", "authorization_code")

	token, err := p.fetchToken(ctx, params)
	if err != nil {
		return nil, fmt.Errorf("error fetching token: %w", err)
	}

	return p.OIDCProvider.createSession(ctx, token, false)
}

// RefreshSession uses the RefreshToken to fetch new Access and ID Tokens
func (p *MicrosoftEntraIDProvider) RefreshSession(ctx context.Context, s *sessions.SessionState) (bool, error) {
	if s == nil || s.RefreshToken == "" {
		return false, nil
	}

	var err error
	ctx = oidc.ClientContext(ctx, requests.DefaultHTTPClient)
	if p.federatedTokenAuth {
		err = p.redeemRefreshTokenWithFederatedToken(ctx, s)
	} else {
		err = p.redeemRefreshToken(ctx, s)
	}

View on GitHub (pinned to 33c2eb92de)

Solutions

  1. Use errors.Unwrap (the error uses %w) to inspect the root cause — HTTP status or transport error tells you which fix applies.
  2. Re-initiate the login flow to get a fresh authorization code; codes are single-use and short-lived.
  3. Verify the Entra app's federated credential (issuer, subject, audience) matches the token file's claims.
  4. Check that redirect_url passed to Redeem exactly matches the redirect URI registered on the app.
  5. Confirm network egress to login.microsoftonline.com from the runtime environment.

Example fix

// before
err := fmt.Errorf("error fetching token: %v", err) // hypothetical: loses unwrapping
// after (as shipped) — inspect with errors.As in the caller
var httpErr interface{ StatusCode() int }
if errors.As(err, &httpErr) { /* handle 4xx/5xx from token endpoint */ }
Defensive patterns

Strategy: try-catch

Try / catch

s, err := provider.Redeem(ctx, redirectURL, code)
if err != nil && strings.Contains(err.Error(), "error fetching token") {
    // error uses %w: inspect the root cause
    log.Printf("token exchange failed: %v (cause: %v)", err, errors.Unwrap(errors.Unwrap(err)))
    http.Error(w, "authentication failed; restart login", http.StatusUnauthorized)
    return
}

Prevention

When it happens

Trigger: Redeem -> redeemWithFederatedToken where the token endpoint request fails: unreachable Entra endpoint, invalid authorization code (already used/expired), federated client assertion rejected (untrusted subject/issuer), redirect_uri mismatch, or malformed token response.

Common situations: Authorization code replayed or expired before redemption; federated credential not registered on the Entra app (subject/issuer mismatch in the federation setup); wrong RedeemURL/redirect URL; corporate proxy blocking login.microsoftonline.com.

Related errors


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