-
Notifications
You must be signed in to change notification settings - Fork 1k
Open
Description
In this code:
Lines 215 to 256 in 014cf77
func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle, styleCache *AuthStyleCache) (*Token, error) { | |
needsAuthStyleProbe := authStyle == AuthStyleUnknown | |
if needsAuthStyleProbe { | |
if style, ok := styleCache.lookupAuthStyle(tokenURL, clientID); ok { | |
authStyle = style | |
needsAuthStyleProbe = false | |
} else { | |
authStyle = AuthStyleInHeader // the first way we'll try | |
} | |
} | |
req, err := newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) | |
if err != nil { | |
return nil, err | |
} | |
token, err := doTokenRoundTrip(ctx, req) | |
if err != nil && needsAuthStyleProbe { | |
// If we get an error, assume the server wants the | |
// clientID & clientSecret in a different form. | |
// See https://code.google.com/p/goauth2/issues/detail?id=31 for background. | |
// In summary: | |
// - Reddit only accepts client secret in the Authorization header | |
// - Dropbox accepts either it in URL param or Auth header, but not both. | |
// - Google only accepts URL param (not spec compliant?), not Auth header | |
// - Stripe only accepts client secret in Auth header with Bearer method, not Basic | |
// | |
// We used to maintain a big table in this code of all the sites and which way | |
// they went, but maintaining it didn't scale & got annoying. | |
// 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) | |
} | |
if needsAuthStyleProbe && err == nil { | |
styleCache.setAuthStyle(tokenURL, clientID, authStyle) | |
} | |
// Don't overwrite `RefreshToken` with an empty value | |
// if this was a token refreshing request. | |
if token != nil && token.RefreshToken == "" { | |
token.RefreshToken = v.Get("refresh_token") | |
} | |
return token, err | |
} |
We first attempt the header auth method, and if it fails, attempt the params method. If it turns out that the header auth method is the correct one, and the params method always fails, we only return the error for the params method and swallow the header auth's failure
I think it would be great to return an error that has both method's errors, but I'm not familiar enough with golang to know whether changing the format of this method will cause breakages anywhere. The method itself is in an internal package, so it's probably okay?
Metadata
Metadata
Assignees
Labels
No labels