code: def get_token_async(self, refresh=False):
      
      key = '%s,%s' % (self.service_account_id, ','.join(self.scopes))
      ts = yield _AE_TokenStorage_.get_by_id_async(
          key,
          use_cache=True,
          use_memcache=self.retry_params.memcache_access_token,
          use_datastore=self.retry_params.save_access_token)
      if refresh or ts is None or ts.expires < (
          time.time() + self.expiration_headroom):
        token, expires_at = yield self.make_token_async(
            self.scopes, self.service_account_id)
        timeout = int(expires_at - time.time())
        ts = _AE_TokenStorage_(id=key, token=token, expires=expires_at)
        if timeout > 0:
          yield ts.put_async(memcache_timeout=timeout,
                             use_datastore=self.retry_params.save_access_token,
                             force_writes=True,
                             use_cache=True,
                             use_memcache=self.retry_params.memcache_access_token)
      raise ndb.Return(ts.token)
docs: Get an authentication token.
  
      The token is cached in memcache, keyed by the scopes argument.
      Uses a random token expiration headroom value generated in the constructor
      to eliminate a burst of GET_ACCESS_TOKEN API requests.
  
      Args:
        refresh: If True, ignore a cached token; default False.
  
      Yields:
        An authentication token. This token is guaranteed to be non-expired.