code: func GetAccessToken(c context.Context, scopes []string) (*oauth2.Token, error) {
  	scopes, cacheKey := normalizeScopes(scopes)
  
  	// Try to find the token in the local memory first. If it expires soon,
  	// refresh it earlier with some probability. That avoids a situation when
  	// parallel requests that use access tokens suddenly see the cache expired
  	// and rush to refresh the token all at once.
  	lru := tokensCache.LRU(c)
  	if tokIface, ok := lru.Get(c, cacheKey); ok {
  		tok := tokIface.(*oauth2.Token)
  		if !closeToExpRandomized(c, tok.Expiry) {
  			return tok, nil
  		}
  	}
  
  	tokIface, err := lru.Create(c, cacheKey, func() (interface{}, time.Duration, error) {
  		// The token needs to be refreshed.
  		logging.Debugf(c, "Getting an access token for scopes %q", strings.Join(scopes, ", "))
  		accessToken, exp, err := info.AccessToken(c, scopes...)
  		if err != nil {
  			return nil, 0, transient.Tag.Apply(err)
  		}
  		now := clock.Now(c)
  		logging.Debugf(c, "The token expires in %s", exp.Sub(now))
  
  		// Prematurely expire it to guarantee all returned token live for at least
  		// 'expirationMinLifetime'.
  		tok := &oauth2.Token{
  			AccessToken: accessToken,
  			Expiry:      exp.Add(-expirationMinLifetime),
  			TokenType:   "Bearer",
  		}
  
  		return tok, now.Sub(tok.Expiry), nil
  	})
  	if err != nil {
  		return nil, err
  	}
  	return tokIface.(*oauth2.Token), nil
  }
docs: // GetAccessToken returns an OAuth access token representing app's service
  // account.
  //
  // If scopes is empty, uses auth.OAuthScopeEmail scope.
  //
  // Implements a caching layer on top of GAE's GetAccessToken RPC. May return
  // transient errors.