Skip to content

Commit a03b4ae

Browse files
authored
document token ownership requirements for Config.Client and ReuseTokenSource
When used with tokens issued by a server supporting refresh token rotation it is unsafe to continuing using the token provided to ReuseTokenSource (including via the Client method of Config) outside of the returned TokenSource and/or Client as it leads to a race condition when the first renewal happens: * If ReuseTokenSource renews its token first, the original token's RefreshToken is now invalid (revoked) and any use/renewal attempt will fail. * If the original token renews its token first, the ReuseTokenSource holds the invliad RefreshToken and will fail on the next usage attempt. #84 has extensive discussion of related risks and complications when trying to cache or store the RefreshToken, but the generic risk of race conditions exists regardless of whether any caching or storage is being attempted and API users must be warned of this possibility.
1 parent 14b275c commit a03b4ae

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

oauth2.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOpti
235235
}
236236

237237
// Client returns an HTTP client using the provided token.
238-
// The token will auto-refresh as necessary. The underlying
238+
// The token will auto-refresh as necessary using a ReuseTokenSource, and
239+
// therefore should not be used directly after this call. The underlying
239240
// HTTP transport will be obtained using the provided context.
240241
// The returned client and its Transport should not be modified.
241242
func (c *Config) Client(ctx context.Context, t *Token) *http.Client {
@@ -368,6 +369,11 @@ func NewClient(ctx context.Context, src TokenSource) *http.Client {
368369
// same token as long as it's valid, starting with t.
369370
// When its cached token is invalid, a new token is obtained from src.
370371
//
372+
// When used with tokens issued by a server implementing refresh token
373+
// rotation the initial token t must be treated as owned by the returned
374+
// TokenSource and not directly used further to avoid race conditions
375+
// associated with refresh token invalidation.
376+
//
371377
// ReuseTokenSource is typically used to reuse tokens from a cache
372378
// (such as a file on disk) between runs of a program, rather than
373379
// obtaining new tokens unnecessarily.

0 commit comments

Comments
 (0)