getting a meaningful error out of oauth token exchange
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 6.6k
- Forks
- 631
- PR merge metrics
- No merged PRs in 30d
Description
I've successfully used this goth library, however, I found that
golang/x/oauth2 eats the server's useful error during Exchange() returning:
oauth2: server response missing access_token
... instead of, for example:
invalid_team_for_non_distributed_app
I used this patch to oauth2 to get the error returned:
diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go
index 0aa16905..3288de96 100644
--- a/vendor/golang.org/x/oauth2/internal/token.go
+++ b/vendor/golang.org/x/oauth2/internal/token.go
@@ -64,6 +64,7 @@ type tokenJSON struct {
TokenType string `json:"token_type"`
RefreshToken string `json:"refresh_token"`
ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number
+ Error string `json:"error"`
}
func (e *tokenJSON) expiry() (t time.Time) {
@@ -216,7 +217,11 @@ func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string,
// So just try both ways.
authStyle = AuthStyleInParams // the second way we'll try
req, _ = newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle)
- token, err = doTokenRoundTrip(ctx, req)
+ var err2 error
+ token, err2 = doTokenRoundTrip(ctx, req)
+ if err2 == nil {
+ err = nil
+ }
}
if needsAuthStyleProbe && err == nil {
setAuthStyle(tokenURL, authStyle)
@@ -245,8 +250,8 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
Body: body,
}
}
+ var errorStr string
var token *Token
content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
switch content {
@@ -266,6 +271,7 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
if expires != 0 {
token.Expiry = time.Now().Add(time.Duration(expires) * time.Second)
}
+ errorStr = vals.Get("error")
default:
var tj tokenJSON
if err = json.Unmarshal(body, &tj); err != nil {
@@ -279,9 +285,14 @@ func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) {
Raw: make(map[string]interface{}),
}
json.Unmarshal(body, &token.Raw) // no error checks for optional fields
+ errorStr = tj.Error
}
if token.AccessToken == "" {
- return nil, errors.New("oauth2: server response missing access_token")
+ err = errors.New("oauth2: server response missing access_token")
+ if errorStr != "" {
+ err = errors.New(errorStr)
+ }
+ return nil, err
}
return token, nil
}
Does anyone have a better solution? My challenge now is were and how to maintain this patch.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing vendor/golang.org/x/oauth2/internal/token.go, especially RetrieveToken and doTokenRoundTrip, and trace how goth reaches Exchange(). Compare the vendored behavior with the upstream oauth2 package and determine how server error responses should be exposed. Done means a maintainable approach preserves meaningful token-exchange errors without relying on an unmaintained local patch.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- authentication, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100