@@ -195,7 +195,7 @@ func (h *OAuthHandler) refreshToken(ctx context.Context, refreshToken string) (*
195
195
196
196
if resp .StatusCode != http .StatusOK {
197
197
body , _ := io .ReadAll (resp .Body )
198
- return nil , fmt . Errorf ( "refresh token request failed with status %d: %s" , resp . StatusCode , body )
198
+ return nil , extractOAuthError ( body , resp . StatusCode , "refresh token request failed" )
199
199
}
200
200
201
201
var tokenResp Token
@@ -232,6 +232,18 @@ func (h *OAuthHandler) GetClientID() string {
232
232
return h .config .ClientID
233
233
}
234
234
235
+ // extractOAuthError attempts to parse an OAuth error response from the response body
236
+ func extractOAuthError (body []byte , statusCode int , context string ) error {
237
+ // Try to parse the error as an OAuth error response
238
+ var oauthErr OAuthError
239
+ if err := json .Unmarshal (body , & oauthErr ); err == nil && oauthErr .ErrorCode != "" {
240
+ return fmt .Errorf ("%s: %w" , context , oauthErr )
241
+ }
242
+
243
+ // If not a valid OAuth error, return the raw response
244
+ return fmt .Errorf ("%s with status %d: %s" , context , statusCode , body )
245
+ }
246
+
235
247
// GetClientSecret returns the client secret
236
248
func (h * OAuthHandler ) GetClientSecret () string {
237
249
return h .config .ClientSecret
@@ -247,6 +259,21 @@ func (h *OAuthHandler) GetExpectedState() string {
247
259
return h .expectedState
248
260
}
249
261
262
+ // OAuthError represents a standard OAuth 2.0 error response
263
+ type OAuthError struct {
264
+ ErrorCode string `json:"error"`
265
+ ErrorDescription string `json:"error_description,omitempty"`
266
+ ErrorURI string `json:"error_uri,omitempty"`
267
+ }
268
+
269
+ // Error implements the error interface
270
+ func (e OAuthError ) Error () string {
271
+ if e .ErrorDescription != "" {
272
+ return fmt .Sprintf ("OAuth error: %s - %s" , e .ErrorCode , e .ErrorDescription )
273
+ }
274
+ return fmt .Sprintf ("OAuth error: %s" , e .ErrorCode )
275
+ }
276
+
250
277
// OAuthProtectedResource represents the response from /.well-known/oauth-protected-resource
251
278
type OAuthProtectedResource struct {
252
279
AuthorizationServers []string `json:"authorization_servers"`
@@ -486,7 +513,7 @@ func (h *OAuthHandler) RegisterClient(ctx context.Context, clientName string) er
486
513
487
514
if resp .StatusCode != http .StatusCreated && resp .StatusCode != http .StatusOK {
488
515
body , _ := io .ReadAll (resp .Body )
489
- return fmt . Errorf ( "registration request failed with status %d: %s" , resp .StatusCode , body )
516
+ return extractOAuthError ( body , resp .StatusCode , "registration request failed" )
490
517
}
491
518
492
519
var regResponse struct {
@@ -566,7 +593,7 @@ func (h *OAuthHandler) ProcessAuthorizationResponse(ctx context.Context, code, s
566
593
567
594
if resp .StatusCode != http .StatusOK {
568
595
body , _ := io .ReadAll (resp .Body )
569
- return fmt . Errorf ( "token request failed with status %d: %s" , resp .StatusCode , body )
596
+ return extractOAuthError ( body , resp .StatusCode , "token request failed" )
570
597
}
571
598
572
599
var tokenResp Token
0 commit comments