{"record":{"id":"1f33c8f5d4f66614","repo":"oauth2-proxy/oauth2-proxy","slug":"error-fetching-token-w","errorCode":null,"errorMessage":"error fetching token: %w","messagePattern":"error fetching token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"providers/ms_entra_id.go","lineNumber":136,"sourceCode":"\t}\n\n\tparams := url.Values{}\n\n\t// Exchange parameters for token federation\n\t// https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#request-an-access-token-with-a-certificate-credential\n\tif codeVerifier != \"\" {\n\t\tparams.Add(\"code_verifier\", codeVerifier)\n\t}\n\tparams.Add(\"redirect_uri\", redirectURL)\n\tparams.Add(\"client_id\", p.ClientID)\n\tparams.Add(\"client_assertion\", string(federatedToken))\n\tparams.Add(\"client_assertion_type\", \"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\")\n\tparams.Add(\"code\", code)\n\tparams.Add(\"grant_type\", \"authorization_code\")\n\n\ttoken, err := p.fetchToken(ctx, params)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error fetching token: %w\", err)\n\t}\n\n\treturn p.OIDCProvider.createSession(ctx, token, false)\n}\n\n// RefreshSession uses the RefreshToken to fetch new Access and ID Tokens\nfunc (p *MicrosoftEntraIDProvider) RefreshSession(ctx context.Context, s *sessions.SessionState) (bool, error) {\n\tif s == nil || s.RefreshToken == \"\" {\n\t\treturn false, nil\n\t}\n\n\tvar err error\n\tctx = oidc.ClientContext(ctx, requests.DefaultHTTPClient)\n\tif p.federatedTokenAuth {\n\t\terr = p.redeemRefreshTokenWithFederatedToken(ctx, s)\n\t} else {\n\t\terr = p.redeemRefreshToken(ctx, s)\n\t}","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/oauth2-proxy/oauth2-proxy/blob/33c2eb92dea78204f7a18bc2dfdbccc220f39257/providers/ms_entra_id.go#L118-L154","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use errors.Unwrap (the error uses %w) to inspect the root cause — HTTP status or transport error tells you which fix applies.","Re-initiate the login flow to get a fresh authorization code; codes are single-use and short-lived.","Verify the Entra app's federated credential (issuer, subject, audience) matches the token file's claims.","Check that redirect_url passed to Redeem exactly matches the redirect URI registered on the app.","Confirm network egress to login.microsoftonline.com from the runtime environment."],"exampleFix":"// before\nerr := fmt.Errorf(\"error fetching token: %v\", err) // hypothetical: loses unwrapping\n// after (as shipped) — inspect with errors.As in the caller\nvar httpErr interface{ StatusCode() int }\nif errors.As(err, &httpErr) { /* handle 4xx/5xx from token endpoint */ }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"s, err := provider.Redeem(ctx, redirectURL, code)\nif err != nil && strings.Contains(err.Error(), \"error fetching token\") {\n    // error uses %w: inspect the root cause\n    log.Printf(\"token exchange failed: %v (cause: %v)\", err, errors.Unwrap(errors.Unwrap(err)))\n    http.Error(w, \"authentication failed; restart login\", http.StatusUnauthorized)\n    return\n}","preventionTips":["Redeem authorization codes immediately; they expire in minutes and are single-use.","Register the federated credential (issuer/subject/audience) on the Entra app before deploying.","Ensure redirect_url passed to Redeem matches the app's registered redirect URI exactly.","Allow egress to login.microsoftonline.com through proxies/firewalls."],"tags":["entra-id","azure","oauth2","token-exchange","federated-identity"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"33c2eb92dea78204f7a18bc2dfdbccc220f39257","analyzedAt":"2026-09-06T08:51:53.077Z","contentChangedAt":"2026-09-06T08:51:53.077Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}