Skip to content

Commit af3f4b1

Browse files
committed
1 parent 68a41d6 commit af3f4b1

File tree

2 files changed

+42
-9
lines changed

2 files changed

+42
-9
lines changed

internal/token.go

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,17 @@ type Token struct {
5858

5959
// tokenJSON is the struct representing the HTTP response from OAuth2
6060
// providers returning a token in JSON form.
61+
// https://datatracker.ietf.org/doc/html/rfc6749#section-5.1
6162
type tokenJSON struct {
6263
AccessToken string `json:"access_token"`
6364
TokenType string `json:"token_type"`
6465
RefreshToken string `json:"refresh_token"`
6566
ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number
67+
// error fields
68+
// https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
69+
Error string `json:"error"`
70+
ErrorDescription string `json:"error_description"`
71+
ErrorUri string `json:"error_uri"`
6672
}
6773

6874
func (e *tokenJSON) expiry() (t time.Time) {
@@ -238,11 +244,12 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
238244
if err != nil {
239245
return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
240246
}
241-
if code := r.StatusCode; code < 200 || code > 299 {
242-
return nil, &RetrieveError{
243-
Response: r,
244-
Body: body,
245-
}
247+
248+
failureStatus := r.StatusCode < 200 || r.StatusCode > 299
249+
retrieveError := &RetrieveError{
250+
Response: r,
251+
Body: body,
252+
// error details populated below
246253
}
247254

248255
var token *Token
@@ -251,8 +258,11 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
251258
case "application/x-www-form-urlencoded", "text/plain":
252259
vals, err := url.ParseQuery(string(body))
253260
if err != nil {
254-
return nil, err
261+
return nil, fmt.Errorf("oauth2: cannot parse response: %v", err)
255262
}
263+
retrieveError.ErrorCode = vals.Get("error")
264+
retrieveError.ErrorDescription = vals.Get("error_description")
265+
retrieveError.ErrorCode = vals.Get("error")
256266
token = &Token{
257267
AccessToken: vals.Get("access_token"),
258268
TokenType: vals.Get("token_type"),
@@ -267,8 +277,14 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
267277
default:
268278
var tj tokenJSON
269279
if err = json.Unmarshal(body, &tj); err != nil {
270-
return nil, err
280+
if failureStatus {
281+
return nil, retrieveError
282+
}
283+
return nil, fmt.Errorf("oauth2: cannot parse json: %v", err)
271284
}
285+
retrieveError.ErrorCode = tj.Error
286+
retrieveError.ErrorDescription = tj.ErrorDescription
287+
retrieveError.ErrorUri = tj.ErrorUri
272288
token = &Token{
273289
AccessToken: tj.AccessToken,
274290
TokenType: tj.TokenType,
@@ -278,17 +294,27 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
278294
}
279295
json.Unmarshal(body, &token.Raw) // no error checks for optional fields
280296
}
297+
if failureStatus || retrieveError.ErrorCode != "" {
298+
return nil, retrieveError
299+
}
281300
if token.AccessToken == "" {
282301
return nil, errors.New("oauth2: server response missing access_token")
283302
}
284303
return token, nil
285304
}
286305

306+
// mirrors oauth2.RetrieveError
287307
type RetrieveError struct {
288-
Response *http.Response
289-
Body []byte
308+
Response *http.Response
309+
Body []byte
310+
ErrorCode string
311+
ErrorDescription string
312+
ErrorUri string
290313
}
291314

292315
func (r *RetrieveError) Error() string {
316+
if r.ErrorCode != "" {
317+
return fmt.Sprintf("oauth2: cannot fetch token: %s %s %s", r.ErrorCode, r.ErrorDescription, r.ErrorUri)
318+
}
293319
return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body)
294320
}

token.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,15 @@ type RetrieveError struct {
171171
// Body is the body that was consumed by reading Response.Body.
172172
// It may be truncated.
173173
Body []byte
174+
// https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
175+
ErrorCode string
176+
ErrorDescription string
177+
ErrorUri string
174178
}
175179

176180
func (r *RetrieveError) Error() string {
181+
if r.ErrorCode != "" {
182+
return fmt.Sprintf("oauth2: cannot fetch token: %s %s %s", r.ErrorCode, r.ErrorDescription, r.ErrorUri)
183+
}
177184
return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body)
178185
}

0 commit comments

Comments
 (0)