golang.org/x/oauth2@v0.18.0/google/appengine_gen1.go (about)

     1  // Copyright 2018 The Go 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  //go:build appengine
     6  
     7  // This file applies to App Engine first generation runtimes (<= Go 1.9).
     8  
     9  package google
    10  
    11  import (
    12  	"context"
    13  	"sort"
    14  	"strings"
    15  	"sync"
    16  
    17  	"golang.org/x/oauth2"
    18  	"google.golang.org/appengine"
    19  )
    20  
    21  func init() {
    22  	appengineTokenFunc = appengine.AccessToken
    23  	appengineAppIDFunc = appengine.AppID
    24  }
    25  
    26  // See comment on AppEngineTokenSource in appengine.go.
    27  func appEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource {
    28  	scopes := append([]string{}, scope...)
    29  	sort.Strings(scopes)
    30  	return &gaeTokenSource{
    31  		ctx:    ctx,
    32  		scopes: scopes,
    33  		key:    strings.Join(scopes, " "),
    34  	}
    35  }
    36  
    37  // aeTokens helps the fetched tokens to be reused until their expiration.
    38  var (
    39  	aeTokensMu sync.Mutex
    40  	aeTokens   = make(map[string]*tokenLock) // key is space-separated scopes
    41  )
    42  
    43  type tokenLock struct {
    44  	mu sync.Mutex // guards t; held while fetching or updating t
    45  	t  *oauth2.Token
    46  }
    47  
    48  type gaeTokenSource struct {
    49  	ctx    context.Context
    50  	scopes []string
    51  	key    string // to aeTokens map; space-separated scopes
    52  }
    53  
    54  func (ts *gaeTokenSource) Token() (*oauth2.Token, error) {
    55  	aeTokensMu.Lock()
    56  	tok, ok := aeTokens[ts.key]
    57  	if !ok {
    58  		tok = &tokenLock{}
    59  		aeTokens[ts.key] = tok
    60  	}
    61  	aeTokensMu.Unlock()
    62  
    63  	tok.mu.Lock()
    64  	defer tok.mu.Unlock()
    65  	if tok.t.Valid() {
    66  		return tok.t, nil
    67  	}
    68  	access, exp, err := appengineTokenFunc(ts.ctx, ts.scopes...)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	tok.t = &oauth2.Token{
    73  		AccessToken: access,
    74  		Expiry:      exp,
    75  	}
    76  	return tok.t, nil
    77  }