github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/golang.org/x/oauth2/google/appengine.go (about) 1 // Copyright 2014 The oauth2 Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package google 6 7 import ( 8 "sort" 9 "strings" 10 "sync" 11 "time" 12 13 "golang.org/x/net/context" 14 "golang.org/x/oauth2" 15 ) 16 17 // Set at init time by appengine_hook.go. If nil, we're not on App Engine. 18 var appengineTokenFunc func(c context.Context, scopes ...string) (token string, expiry time.Time, err error) 19 20 // AppEngineTokenSource returns a token source that fetches tokens 21 // issued to the current App Engine application's service account. 22 // If you are implementing a 3-legged OAuth 2.0 flow on App Engine 23 // that involves user accounts, see oauth2.Config instead. 24 // 25 // The provided context must have come from appengine.NewContext. 26 func AppEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource { 27 if appengineTokenFunc == nil { 28 panic("google: AppEngineTokenSource can only be used on App Engine.") 29 } 30 scopes := append([]string{}, scope...) 31 sort.Strings(scopes) 32 return &appEngineTokenSource{ 33 ctx: ctx, 34 scopes: scopes, 35 key: strings.Join(scopes, " "), 36 } 37 } 38 39 // aeTokens helps the fetched tokens to be reused until their expiration. 40 var ( 41 aeTokensMu sync.Mutex 42 aeTokens = make(map[string]*tokenLock) // key is space-separated scopes 43 ) 44 45 type tokenLock struct { 46 mu sync.Mutex // guards t; held while fetching or updating t 47 t *oauth2.Token 48 } 49 50 type appEngineTokenSource struct { 51 ctx context.Context 52 scopes []string 53 key string // to aeTokens map; space-separated scopes 54 } 55 56 func (ts *appEngineTokenSource) Token() (*oauth2.Token, error) { 57 if appengineTokenFunc == nil { 58 panic("google: AppEngineTokenSource can only be used on App Engine.") 59 } 60 61 aeTokensMu.Lock() 62 tok, ok := aeTokens[ts.key] 63 if !ok { 64 tok = &tokenLock{} 65 aeTokens[ts.key] = tok 66 } 67 aeTokensMu.Unlock() 68 69 tok.mu.Lock() 70 defer tok.mu.Unlock() 71 if tok.t.Valid() { 72 return tok.t, nil 73 } 74 access, exp, err := appengineTokenFunc(ts.ctx, ts.scopes...) 75 if err != nil { 76 return nil, err 77 } 78 tok.t = &oauth2.Token{ 79 AccessToken: access, 80 Expiry: exp, 81 } 82 return tok.t, nil 83 }