mirror of
https://github.com/golang/oauth2.git
synced 2025-07-21 00:00:09 +08:00
Token caching is now done whenever you make a Client, and ReuseTokenSource is exported from the oauth2 package and used by the Google TokenSources (Compute and App Engine). Token.Expired is now Token.Valid, and works on nil receivers. Some other wording cleanups in the process. All tests pass. App Engine should pass, but is untested. Change-Id: Ibe1d2599ac3ccfe9b399b1672f74bb24cfc8d311 Reviewed-on: https://go-review.googlesource.com/2195 Reviewed-by: Burcu Dogan <jbd@google.com>
72 lines
1.6 KiB
Go
72 lines
1.6 KiB
Go
// Copyright 2014 The oauth2 Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package google
|
|
|
|
import (
|
|
"errors"
|
|
"sort"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"golang.org/x/oauth2"
|
|
)
|
|
|
|
var (
|
|
aeTokensMu sync.Mutex // guards aeTokens and appEngineTokenSource.key
|
|
|
|
// aeTokens helps the fetched tokens to be reused until their expiration.
|
|
aeTokens = make(map[string]*tokenLock) // key is '\0'-separated scopes
|
|
)
|
|
|
|
var errInvalidContext = errors.New("oauth2: a valid appengine.Context is required")
|
|
|
|
type tokenLock struct {
|
|
mu sync.Mutex // guards t; held while updating t
|
|
t *oauth2.Token
|
|
}
|
|
|
|
type appEngineTokenSource struct {
|
|
ctx oauth2.Context
|
|
|
|
// fetcherFunc makes the actual RPC to fetch a new access
|
|
// token with an expiry time. Provider of this function is
|
|
// responsible to assert that the given context is valid.
|
|
fetcherFunc func(ctx oauth2.Context, scope ...string) (accessToken string, expiry time.Time, err error)
|
|
|
|
// scopes and key are guarded by the package-level mutex aeTokensMu
|
|
scopes []string
|
|
key string
|
|
}
|
|
|
|
func (ts *appEngineTokenSource) Token() (*oauth2.Token, error) {
|
|
aeTokensMu.Lock()
|
|
if ts.key == "" {
|
|
sort.Sort(sort.StringSlice(ts.scopes))
|
|
ts.key = strings.Join(ts.scopes, string(0))
|
|
}
|
|
tok, ok := aeTokens[ts.key]
|
|
if !ok {
|
|
tok = &tokenLock{}
|
|
aeTokens[ts.key] = tok
|
|
}
|
|
aeTokensMu.Unlock()
|
|
|
|
tok.mu.Lock()
|
|
defer tok.mu.Unlock()
|
|
if tok.t.Valid() {
|
|
return tok.t, nil
|
|
}
|
|
access, exp, err := ts.fetcherFunc(ts.ctx, ts.scopes...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
tok.t = &oauth2.Token{
|
|
AccessToken: access,
|
|
Expiry: exp,
|
|
}
|
|
return tok.t, nil
|
|
}
|