Skip to content

Commit 3b9c415

Browse files
committed
fix(oauth): check for oauth error responses even when status code is 200
Certain providers (**cough** GitHub **cough**) return HTTP 200 responses with an error in the body for their OAuth token exchange and token refresh endpoints. Previously, we only checked for non-200 status codes, which could lead to us missing the errors, attempting to unmarshal the body as a token, failing to detect the error, and even saving the empty token. This commit attempts to unmarshal the body as an OAuth error response even when the status code is 200. If the body is not an OAuth error response, we fall back to the previous behavior.
1 parent 254cb2d commit 3b9c415

File tree

2 files changed

+519
-2
lines changed

2 files changed

+519
-2
lines changed

client/transport/oauth.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,21 @@ func (h *OAuthHandler) refreshToken(ctx context.Context, refreshToken string) (*
246246
return nil, extractOAuthError(body, resp.StatusCode, "refresh token request failed")
247247
}
248248

249+
// Read the response body for parsing
250+
body, err := io.ReadAll(resp.Body)
251+
if err != nil {
252+
return nil, fmt.Errorf("failed to read token response body: %w", err)
253+
}
254+
255+
// GitHub returns HTTP 200 even for errors, with error details in the JSON body
256+
// Check if the response contains an error field before parsing as Token
257+
var oauthErr OAuthError
258+
if err := json.Unmarshal(body, &oauthErr); err == nil && oauthErr.ErrorCode != "" {
259+
return nil, extractOAuthError(body, resp.StatusCode, "refresh token request failed")
260+
}
261+
249262
var tokenResp Token
250-
if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
263+
if err := json.Unmarshal(body, &tokenResp); err != nil {
251264
return nil, fmt.Errorf("failed to decode token response: %w", err)
252265
}
253266

@@ -679,8 +692,21 @@ func (h *OAuthHandler) ProcessAuthorizationResponse(ctx context.Context, code, s
679692
return extractOAuthError(body, resp.StatusCode, "token request failed")
680693
}
681694

695+
// Read the response body for parsing
696+
body, err := io.ReadAll(resp.Body)
697+
if err != nil {
698+
return fmt.Errorf("failed to read token response body: %w", err)
699+
}
700+
701+
// GitHub returns HTTP 200 even for errors, with error details in the JSON body
702+
// Check if the response contains an error field before parsing as Token
703+
var oauthErr OAuthError
704+
if err := json.Unmarshal(body, &oauthErr); err == nil && oauthErr.ErrorCode != "" {
705+
return extractOAuthError(body, resp.StatusCode, "token request failed")
706+
}
707+
682708
var tokenResp Token
683-
if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
709+
if err := json.Unmarshal(body, &tokenResp); err != nil {
684710
return fmt.Errorf("failed to decode token response: %w", err)
685711
}
686712

0 commit comments

Comments
 (0)