// Copyright 2015 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package auth implements a wrapper around golang.org/x/oauth2.
//
// Its main improvement is the on-disk cache for OAuth tokens, which is
// especially important for 3-legged interactive OAuth flows: its usage
// eliminates annoying login prompts each time a program is used (because the
// refresh token can now be reused). The cache also allows to reduce unnecessary
// token refresh calls when sharing a service account between processes.
//
// The package also implements some best practices regarding interactive login
// flows in CLI programs. It makes it easy to implement a login process as
// a separate interactive step that happens before the main program loop.
//
// The antipattern it tries to prevent is "launch an interactive login flow
// whenever program hits 'Not Authorized' response from the server". This
// usually results in a very confusing behavior, when login prompts pop up
// unexpectedly at random time, random places and from multiple goroutines at
// once, unexpectedly consuming unintended stdin input.
package auth

import (
	"context"
	"fmt"
	"net/http"
	"path/filepath"
	"sort"
	"strings"
	"sync"
	"time"

	"cloud.google.com/go/compute/metadata"

	"golang.org/x/oauth2"
	"google.golang.org/grpc/credentials"

	"go.chromium.org/luci/auth/internal"
	"go.chromium.org/luci/common/clock"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/common/retry"
	"go.chromium.org/luci/common/retry/transient"
	"go.chromium.org/luci/lucictx"
)

var (
	// ErrLoginRequired is returned by Transport() in case long term credentials
	// are not cached and the user must go through interactive login.
	ErrLoginRequired = errors.New("interactive login is required")

	// ErrInsufficientAccess is returned by Login() or Transport() if an access
	// token can't be minted for given OAuth scopes. For example if a GCE instance
	// wasn't granted access to requested scopes when it was created.
	ErrInsufficientAccess = internal.ErrInsufficientAccess

	// ErrBadCredentials is returned by authenticating RoundTripper if service
	// account key used to generate access tokens is revoked, malformed or can not
	// be read from disk.
	ErrBadCredentials = internal.ErrBadCredentials

	// ErrNoEmail is returned by GetEmail() if the cached credentials are not
	// associated with some particular email. This may happen, for example, when
	// using a refresh token that doesn't have 'userinfo.email' scope.
	ErrNoEmail = errors.New("the token is not associated with an email")

	// ErrBadOptions is returned by Login() or Transport() if Options passed
	// to authenticator indicate incompatible features. This likely indicates
	// a programming error.
	ErrBadOptions = errors.New("bad authenticator options")
)

// Some known Google API OAuth scopes.
const (
	OAuthScopeEmail = "https://www.googleapis.com/auth/userinfo.email"
	OAuthScopeIAM   = "https://www.googleapis.com/auth/iam"
)

const (
	// GCEServiceAccount is special value that can be passed instead of path to
	// a service account credentials file to indicate that GCE VM credentials should
	// be used instead of a real credentials file.
	GCEServiceAccount = ":gce"
)

// Method defines a method to use to obtain OAuth access token.
type Method string

// Supported authentication methods.
const (
	// AutoSelectMethod can be used to allow the library to pick a method most
	// appropriate for given set of options and the current execution environment.
	//
	// For example, passing ServiceAccountJSONPath or ServiceAccountJSON makes
	// Authenticator to pick ServiceAccountMethod.
	//
	// See SelectBestMethod function for details.
	AutoSelectMethod Method = ""

	// UserCredentialsMethod is used for interactive OAuth 3-legged login flow.
	//
	// Using this method requires specifying an OAuth client by passing ClientID
	// and ClientSecret in Options when calling NewAuthenticator.
	//
	// Additionally, SilentLogin and OptionalLogin (i.e. non-interactive) login
	// modes rely on a presence of a refresh token in the token cache, thus using
	// these modes with UserCredentialsMethod also requires configured token
	// cache (see SecretsDir field of Options).
	UserCredentialsMethod Method = "UserCredentialsMethod"

	// ServiceAccountMethod is used to authenticate as a service account using
	// a private key.
	//
	// Callers of NewAuthenticator must pass either a path to a JSON file with
	// service account key (as produced by Google Cloud Console) or a body of this
	// JSON file. See ServiceAccountJSONPath and ServiceAccountJSON fields in
	// Options.
	//
	// Using ServiceAccountJSONPath has an advantage: Authenticator always loads
	// the private key from the file before refreshing the token, it allows to
	// replace the key while the process is running.
	ServiceAccountMethod Method = "ServiceAccountMethod"

	// GCEMetadataMethod is used on Compute Engine to use tokens provided by
	// Metadata server. See https://cloud.google.com/compute/docs/authentication
	GCEMetadataMethod Method = "GCEMetadataMethod"

	// LUCIContextMethod is used by LUCI-aware applications to fetch tokens though
	// a local auth server (discoverable via "local_auth" key in LUCI_CONTEXT).
	//
	// This method is similar in spirit to GCEMetadataMethod: it uses some local
	// HTTP server as a provider of OAuth access tokens, which gives an ambient
	// authentication context to apps that use it.
	//
	// There are some big differences:
	//  1. LUCIContextMethod supports minting tokens for multiple different set
	//     of scopes, unlike GCE metadata server that always gives a token with
	//     preconfigured scopes (set when the GCE instance was created).
	//  2. LUCIContextMethod is not GCE-specific. It doesn't use magic link-local
	//     IP address. It can run on any machine.
	//  3. The access to the local auth server is controlled by file system
	//     permissions of LUCI_CONTEXT file (there's a secret in this file).
	//  4. There can be many local auth servers running at once (on different
	//     ports). Useful for bringing up sub-contexts, in particular in
	//     combination with ActAsServiceAccount ("sudo" mode) or for tests.
	//
	// See auth/integration/localauth package for the implementation of the server
	// side of the protocol.
	LUCIContextMethod Method = "LUCIContextMethod"
)

// LoginMode is used as enum in NewAuthenticator function.
type LoginMode string

const (
	// InteractiveLogin indicates to Authenticator that it is okay to run an
	// interactive login flow (via Login()) in Transport(), Client() or other
	// factories if there's no cached token.
	//
	// This is typically used with UserCredentialsMethod to generate an OAuth
	// refresh token and put it in the token cache at the start of the program,
	// when grabbing a transport.
	//
	// Has no effect when used with service account credentials.
	InteractiveLogin LoginMode = "InteractiveLogin"

	// SilentLogin indicates to Authenticator that it must return a transport that
	// implements authentication, but it is NOT OK to run interactive login flow
	// to make it.
	//
	// Transport() and other factories will fail with ErrLoginRequired error if
	// there's no cached token or one can't be generated on the fly in
	// non-interactive mode. This may happen when using UserCredentialsMethod.
	//
	// It is always OK to use SilentLogin mode with service accounts credentials
	// (ServiceAccountMethod mode), since no user interaction is necessary to
	// generate an access token in this case.
	SilentLogin LoginMode = "SilentLogin"

	// OptionalLogin indicates to Authenticator that it should return a transport
	// that implements authentication, but it is OK to return non-authenticating
	// transport if there are no valid cached credentials.
	//
	// An interactive login flow will never be invoked. An unauthenticated client
	// will be returned if no credentials are present.
	//
	// Can be used when making calls to backends that allow anonymous access. This
	// is especially useful with UserCredentialsMethod: a user may start using
	// the service right away (in anonymous mode), and later login (using Login()
	// method or any other way of initializing credentials cache) to get more
	// permissions.
	//
	// When used with ServiceAccountMethod it is identical to SilentLogin, since
	// it makes no sense to ignore invalid service account credentials when the
	// caller is explicitly asking the authenticator to use them.
	//
	// Has the original meaning when used with GCEMetadataMethod: it instructs to
	// skip authentication if the token returned by GCE metadata service doesn't
	// have all requested scopes.
	OptionalLogin LoginMode = "OptionalLogin"
)

// Options are used by NewAuthenticator call.
type Options struct {
	// Transport is underlying round tripper to use for requests.
	//
	// Default: http.DefaultTransport.
	Transport http.RoundTripper

	// Method defines how to grab OAuth2 tokens.
	//
	// Default: AutoSelectMethod.
	Method Method

	// Scopes is a list of OAuth scopes to request.
	//
	// Default: [OAuthScopeEmail].
	Scopes []string

	// ActAsServiceAccount is used to act as a specified service account email.
	//
	// When this option is set, there are two identities involved:
	//  1. A service account identity specified by `ActAsServiceAccount`.
	//  2. An identity conveyed by the authenticator options (via cached refresh
	//     token, or via `ServiceAccountJSON`, or other similar ways), i.e. the
	//     identity asserted by the authenticator in case `ActAsServiceAccount` is
	//     not set. It is referred to below as the Actor identity.
	//
	// The resulting authenticator will produce access tokens for service account
	// `ActAsServiceAccount`, using the Actor identity to generate them via some
	// "acting" API.
	//
	// If `ActViaLUCIRealm` is not set, the "acting" API is Google Cloud IAM.
	// The Actor credentials will internally be used to generate access tokens
	// with IAM scope (see `OAuthScopeIAM`). These tokens will then be used to
	// call `generateAccessToken` Cloud IAM RPC to obtain the final tokens that
	// belong to the service account `ActAsServiceAccount`. This requires the
	// Actor to have "iam.serviceAccounts.getAccessToken" Cloud IAM permission,
	// which is usually granted via "Service Account Token Creator" IAM role.
	//
	// If `ActViaLUCIRealm` is set, the "acting" API is the LUCI Token Server.
	// The Actor credentials will internally be used to generate access tokens
	// with just email scope (see `OAuthScopeEmail`). These tokens will then be
	// used to call `MintServiceAccountToken` RPC. This requires the following
	// LUCI permissions in the realm specified by `ActViaLUCIRealm`:
	//  1. The Actor needs "luci.serviceAccounts.mintToken" permission.
	//  2. The target service account needs "luci.serviceAccounts.existInRealm"
	//     permission.
	//  3. The LUCI project the realm belongs to must be authorized to use the
	//     target service account (currently via project_owned_accounts.cfg global
	//     config file).
	//
	// Regardless of what "acting" API is used, `Scopes` parameter specifies what
	// OAuth scopes to request for the final access token belonging to
	// `ActAsServiceAccount`.
	//
	// Default: none.
	ActAsServiceAccount string

	// ActViaLUCIRealm is a LUCI Realm to use to authorize access to the service
	// account when "acting" as it through a LUCI Token Server.
	//
	// See `ActAsServiceAccount` for a detailed explanation.
	//
	// Should have form "<project>:<realm>" (e.g. "chromium:ci"). It instructs
	// the Token Server to lookup acting permissions in a realm named "<realm>",
	// defined in `realms.cfg` project config file in a LUCI project named
	// "<project>".
	//
	// Using this option requires `TokenServerHost` to be set.
	//
	// Default: none.
	ActViaLUCIRealm string

	// TokenServerHost is a hostname of a LUCI Token Server to use when acting.
	//
	// Used only when `ActAsServiceAccount` and `ActViaLUCIRealm` are set.
	//
	// Default: none.
	TokenServerHost string

	// ClientID is OAuth client ID to use with UserCredentialsMethod.
	//
	// See https://developers.google.com/identity/protocols/OAuth2InstalledApp
	// (in particular everything related to "Desktop apps").
	//
	// Together with Scopes forms a cache key in the token cache, which in
	// practical terms means there can be only one concurrently "logged in" user
	// per [ClientID, Scopes] combination. So if multiple binaries use exact same
	// ClientID and Scopes, they'll share credentials cache (a login in one app
	// makes the user logged in in the other app too).
	//
	// If you don't want to share login information between tools, use separate
	// ClientID or SecretsDir values.
	//
	// If not set, UserCredentialsMethod auth method will not work.
	//
	// Default: none.
	ClientID string

	// ClientSecret is OAuth client secret to use with UserCredentialsMethod.
	//
	// Default: none.
	ClientSecret string

	// ServiceAccountJSONPath is a path to a JSON blob with a private key to use.
	//
	// Can also be set to GCEServiceAccount (':gce') to indicate that the GCE VM
	// service account should be used instead. Useful in CLI interfaces. This
	// works only if Method is set to AutoSelectMethod (which is the default for
	// most CLI apps). If GCEServiceAccount is used on non-GCE machine,
	// authenticator methods return ErrBadCredentials.
	//
	// Used only with ServiceAccountMethod.
	ServiceAccountJSONPath string

	// ServiceAccountJSON is a body of JSON key file to use.
	//
	// Overrides ServiceAccountJSONPath if given.
	ServiceAccountJSON []byte

	// GCEAccountName is an account name to query to fetch token for from metadata
	// server when GCEMetadataMethod is used.
	//
	// If given account wasn't granted required set of scopes during instance
	// creation time, Transport() call fails with ErrInsufficientAccess.
	//
	// Default: "default" account.
	GCEAccountName string

	// GCEAllowAsDefault indicates whether it is OK to pick GCE authentication
	// method as default if no other methods apply.
	//
	// Effective only when running on GCE and Method is set to AutoSelectMethod.
	//
	// In theory using GCE metadata server for authentication when it is
	// available looks attractive. In practice, especially if running in a
	// heterogeneous fleet with a mix of GCE and non-GCE machines, automatically
	// enabling GCE-based authentication is very surprising when it happens.
	//
	// Default: false (don't "sniff" GCE environment).
	GCEAllowAsDefault bool

	// SecretsDir can be used to set the path to a directory where tokens
	// are cached.
	//
	// If not set, tokens will be cached only in the process memory. For refresh
	// tokens it means the user would have to go through the login process each
	// time process is started. For service account tokens it means there'll be
	// HTTP round trip to OAuth backend to generate access token each time the
	// process is started.
	SecretsDir string

	// DisableMonitoring can be used to disable the monitoring instrumentation.
	//
	// The transport produced by this authenticator sends tsmon metrics IFF:
	//  1. DisableMonitoring is false (default).
	//  2. The context passed to 'NewAuthenticator' has monitoring initialized.
	DisableMonitoring bool

	// MonitorAs is used for 'client' field of monitoring metrics.
	//
	// The default is 'luci-go'.
	MonitorAs string

	// MinTokenLifetime defines a minimally acceptable lifetime of access tokens
	// generated internally by authenticating http.RoundTripper, TokenSource and
	// PerRPCCredentials.
	//
	// Not used when GetAccessToken is called directly (it accepts this parameter
	// as an argument).
	//
	// The default is 2 min. There's rarely a need to change it and using smaller
	// values may be dangerous (e.g. if the request gets stuck somewhere or the
	// token is cached incorrectly it may expire before it is checked).
	MinTokenLifetime time.Duration

	// testingBaseTokenProvider is used in unit tests.
	testingBaseTokenProvider internal.TokenProvider
	// testingIAMTokenProvider is used in unit tests.
	testingIAMTokenProvider internal.TokenProvider
}

// SelectBestMethod returns a most appropriate authentication method for the
// given set of options and the current execution environment.
//
// Invoked by Authenticator if AutoSelectMethod is passed as Method in Options.
// It picks the first applicable method in this order:
//   * ServiceAccountMethod (if the service account private key is configured).
//   * LUCIContextMethod (if running inside LUCI_CONTEXT with an auth server).
//   * GCEMetadataMethod (if running on GCE and GCEAllowAsDefault is true).
//   * UserCredentialsMethod (if no other method applies).
//
// Beware: it may do relatively heavy calls on first usage (to detect GCE
// environment). Fast after that.
func SelectBestMethod(ctx context.Context, opts Options) Method {
	// Asked to use JSON private key.
	if opts.ServiceAccountJSONPath != "" || len(opts.ServiceAccountJSON) != 0 {
		if opts.ServiceAccountJSONPath == GCEServiceAccount {
			return GCEMetadataMethod
		}
		return ServiceAccountMethod
	}

	// Have a local auth server and an account we are allowed to pick by default.
	// If no default account is given, don't automatically pick up this method.
	if la := lucictx.GetLocalAuth(ctx); la != nil && la.DefaultAccountId != "" {
		return LUCIContextMethod
	}

	// Running on GCE and callers are fine with automagically picking up GCE
	// metadata server.
	if opts.GCEAllowAsDefault && metadata.OnGCE() {
		return GCEMetadataMethod
	}

	return UserCredentialsMethod
}

// AllowsArbitraryScopes returns true if given authenticator options allow
// generating tokens for arbitrary set of scopes.
//
// For example, using a private key to sign assertions allows to mint tokens
// for any set of scopes (since there's no restriction on what scopes we can
// put into JWT to be signed).
//
// On other hand, using e.g GCE metadata server restricts us to use only scopes
// assigned to GCE instance when it was created.
func AllowsArbitraryScopes(ctx context.Context, opts Options) bool {
	if opts.Method == AutoSelectMethod {
		opts.Method = SelectBestMethod(ctx, opts)
	}
	switch {
	case opts.Method == ServiceAccountMethod:
		// A private key can be used to generate tokens with any combination of
		// scopes.
		return true
	case opts.Method == LUCIContextMethod:
		// We can ask the local auth server for any combination of scopes.
		return true
	case opts.ActAsServiceAccount != "":
		// When using derived tokens the authenticator can ask the corresponding API
		// (Cloud IAM's generateAccessToken or LUCI's MintServiceAccountToken) for
		// any scopes it wants.
		return true
	}
	return false
}

// Authenticator is a factory for http.RoundTripper objects that know how to use
// cached OAuth credentials and how to send monitoring metrics (if tsmon package
// was imported).
//
// Authenticator also knows how to run interactive login flow, if required.
type Authenticator struct {
	// Immutable members.
	loginMode    LoginMode
	opts         *Options
	transport    http.RoundTripper
	ctx          context.Context
	testingCache internal.TokenCache // set in unit tests

	// Mutable members.
	lock sync.RWMutex
	err  error

	// baseToken is a token (and its provider and cache) whose possession is
	// sufficient to get the final access token used for authentication of user
	// calls (see 'authToken' below).
	//
	// Methods like 'CheckLoginRequired' check that the base token exists in the
	// cache or can be generated on the fly.
	//
	// In actor mode, the base token has scopes necessary for the corresponding
	// acting API to work (e.g. IAM scope when using Cloud's generateAccessToken).
	// The base token is also always using whatever auth method was specified by
	// Options.Method.
	//
	// In non-actor mode, baseToken coincides with authToken: both point to the
	// exact same struct.
	baseToken *tokenWithProvider

	// authToken is a token (and its provider and cache) that is actually used for
	// authentication of user calls.
	//
	// It is a token returned by 'GetAccessToken'. It is always scoped to 'Scopes'
	// list, as passed to NewAuthenticator via Options.
	//
	// In actor mode, it is derived from the base token by using some "acting" API
	// (which one depends on Options, see ActAsServiceAccount comment). This
	// process is non-interactive and thus can always be performed as long as we
	// have the base token.
	//
	// In non-actor mode it is the main token generated by the authenticator. In
	// this case it coincides with baseToken: both point to the exact same object.
	authToken *tokenWithProvider
}

// NewAuthenticator returns a new instance of Authenticator given its options.
//
// The authenticator is essentially a factory for http.RoundTripper that knows
// how to use OAuth2 tokens. It is bound to the given context: uses its logger,
// clock, transport and deadline.
func NewAuthenticator(ctx context.Context, loginMode LoginMode, opts Options) *Authenticator {
	// Add default scope, sort scopes.
	if len(opts.Scopes) == 0 {
		opts.Scopes = []string{OAuthScopeEmail}
	} else {
		opts.Scopes = append([]string(nil), opts.Scopes...) // copy
		sort.Strings(opts.Scopes)
	}

	// Fill in blanks with default values.
	if opts.GCEAccountName == "" {
		opts.GCEAccountName = "default"
	}
	if opts.Transport == nil {
		opts.Transport = http.DefaultTransport
	}
	if opts.MinTokenLifetime == 0 {
		opts.MinTokenLifetime = 2 * time.Minute
	}

	// TODO(vadimsh): Check SecretsDir permissions. It should be 0700.
	if opts.SecretsDir != "" && !filepath.IsAbs(opts.SecretsDir) {
		var err error
		opts.SecretsDir, err = filepath.Abs(opts.SecretsDir)
		if err != nil {
			panic(fmt.Errorf("failed to get abs path to token cache dir: %s", err))
		}
	}

	// See ensureInitialized for the rest of the initialization.
	auth := &Authenticator{
		ctx:       ctx,
		loginMode: loginMode,
		opts:      &opts,
	}
	auth.transport = NewModifyingTransport(opts.Transport, auth.authTokenInjector)

	// Include the token refresh time into the monitored request time.
	if globalInstrumentTransport != nil && !opts.DisableMonitoring {
		monitorAs := opts.MonitorAs
		if monitorAs == "" {
			monitorAs = "luci-go"
		}
		instrumented := globalInstrumentTransport(ctx, auth.transport, monitorAs)
		if instrumented != auth.transport {
			logging.Debugf(ctx, "Enabling monitoring instrumentation (client == %q)", monitorAs)
			auth.transport = instrumented
		}
	}

	return auth
}

// Transport optionally performs a login and returns http.RoundTripper.
//
// It is a high level wrapper around CheckLoginRequired() and Login() calls. See
// documentation for LoginMode for more details.
func (a *Authenticator) Transport() (http.RoundTripper, error) {
	switch useAuth, err := a.doLoginIfRequired(false); {
	case err != nil:
		return nil, err
	case useAuth:
		return a.transport, nil // token-injecting transport
	default:
		return a.opts.Transport, nil // original non-authenticating transport
	}
}

// Client optionally performs a login and returns http.Client.
//
// It uses transport returned by Transport(). See documentation for LoginMode
// for more details.
func (a *Authenticator) Client() (*http.Client, error) {
	transport, err := a.Transport()
	if err != nil {
		return nil, err
	}
	return &http.Client{Transport: transport}, nil
}

// TokenSource optionally performs a login and returns oauth2.TokenSource.
//
// Can be used for interoperability with libraries that use golang.org/x/oauth2.
//
// It doesn't support 'OptionalLogin' mode, since oauth2.TokenSource must return
// some token. Otherwise its logic is similar to Transport(). In particular it
// may return ErrLoginRequired if interactive login is required, but the
// authenticator is in the silent mode. See LoginMode enum for more details.
func (a *Authenticator) TokenSource() (oauth2.TokenSource, error) {
	if _, err := a.doLoginIfRequired(true); err != nil {
		return nil, err
	}
	return tokenSource{a}, nil
}

// PerRPCCredentials optionally performs a login and returns PerRPCCredentials.
//
// It can be used to authenticate outbound gPRC RPC's.
//
// Has same logic as Transport(), in particular supports OptionalLogin mode.
// See Transport() for more details.
func (a *Authenticator) PerRPCCredentials() (credentials.PerRPCCredentials, error) {
	switch useAuth, err := a.doLoginIfRequired(false); {
	case err != nil:
		return nil, err
	case useAuth:
		return perRPCCreds{a}, nil // token-injecting PerRPCCredentials
	default:
		return perRPCCreds{}, nil // noop PerRPCCredentials
	}
}

// GetAccessToken returns a valid access token with specified minimum lifetime.
//
// Does not interact with the user. May return ErrLoginRequired.
func (a *Authenticator) GetAccessToken(lifetime time.Duration) (*oauth2.Token, error) {
	tok, err := a.currentToken()
	if err != nil {
		return nil, err
	}
	// Impose some arbitrary limit, since <= 0 lifetime won't work.
	if lifetime < time.Second {
		lifetime = time.Second
	}
	if tok == nil || internal.TokenExpiresInRnd(a.ctx, tok, lifetime) {
		// Give 5 sec extra to make sure callers definitely receive a token that
		// has at least 'lifetime' seconds of life left. Without this margin, we
		// can get into an unlucky situation where the token is valid here, but
		// no longer valid (has fewer than 'lifetime' life left) up the stack, due
		// to the passage of time.
		var err error
		tok, err = a.refreshToken(tok, lifetime+5*time.Second)
		if err != nil {
			return nil, err
		}
		// Note: no randomization here. It is a sanity check that verifies
		// refreshToken did its job.
		if internal.TokenExpiresIn(a.ctx, tok, lifetime) {
			return nil, fmt.Errorf("auth: failed to refresh the token")
		}
	}
	return &tok.Token, nil
}

// GetEmail returns an email associated with the credentials.
//
// In most cases this is a fast call that hits the cache. In some rare cases it
// may do an RPC to the Token Info endpoint to grab an email associated with the
// token.
//
// Returns ErrNoEmail if the email is not available. This may happen, for
// example, when using a refresh token that doesn't have 'userinfo.email' scope.
// Callers must expect this error to show up and should prepare a fallback.
//
// Returns an error if the email can't be fetched due to some other transient
// or fatal error. In particular, returns ErrLoginRequired if interactive login
// is required to get the token in the first place.
func (a *Authenticator) GetEmail() (string, error) {
	// Grab last known token and its associated email. Note that this call also
	// initializes the guts of the authenticator, including a.authToken.
	tok, err := a.currentToken()
	switch {
	case err != nil:
		return "", err
	case tok != nil && tok.Email == internal.NoEmail:
		return "", ErrNoEmail
	case tok != nil && tok.Email != internal.UnknownEmail:
		return tok.Email, nil
	}

	// There's no token cached yet (and thus email is not known). First try to ask
	// the provider for email only. Most providers can return it without doing any
	// RPCs or heavy calls. If this is not supported, resort to a heavier code
	// paths that actually refreshes the token and grabs its email along the way.
	a.lock.RLock()
	email := a.authToken.provider.Email()
	a.lock.RUnlock()
	switch {
	case email == internal.NoEmail:
		return "", ErrNoEmail
	case email != "":
		return email, nil
	}

	// The provider doesn't know the email. We need a forceful token refresh to
	// grab it (or discover it is NoEmail). This is relatively rare. It happens
	// only when using UserAuth TokenProvider and there's no cached token at all
	// or it is in old format that don't have email field.
	//
	// Pass -1 as lifetime to force trigger the refresh right now.
	tok, err = a.refreshToken(tok, -1)
	switch {
	case err != nil:
		return "", err
	case tok.Email == internal.NoEmail:
		return "", ErrNoEmail
	case tok.Email == internal.UnknownEmail: // this must not happen, but let's be cautious
		return "", fmt.Errorf("internal error when fetching the email, see logs")
	default:
		return tok.Email, nil
	}
}

// CheckLoginRequired decides whether an interactive login is required.
//
// It examines the token cache and the configured authentication method to
// figure out whether we can attempt to grab an access token without involving
// the user interaction.
//
// Note: it does not check that the cached refresh token is still valid (i.e.
// not revoked). A revoked token will result in ErrLoginRequired error on a
// first attempt to use it.
//
// Returns:
//   * nil if we have a valid cached token or can mint one on the fly.
//   * ErrLoginRequired if we have no cached token and need to bother the user.
//   * ErrInsufficientAccess if the configured auth method can't mint the token
//     we require (e.g when using GCE method and the instance doesn't have all
//     requested OAuth scopes).
//   * Generic error on other unexpected errors.
func (a *Authenticator) CheckLoginRequired() error {
	a.lock.Lock()
	defer a.lock.Unlock()

	if err := a.ensureInitialized(); err != nil {
		return err
	}

	// No cached base token and the token provider requires interaction with the
	// user: need to login. Only non-interactive token providers are allowed to
	// mint tokens on the fly, see refreshToken.
	if a.baseToken.token == nil && a.baseToken.provider.RequiresInteraction() {
		return ErrLoginRequired
	}

	return nil
}

// Login perform an interaction with the user to get a long term refresh token
// and cache it.
//
// Blocks for user input, can use stdin. It overwrites currently cached
// credentials, if any.
//
// When used with non-interactive token providers (e.g. based on service
// accounts), just clears the cached access token, so next the next
// authenticated call gets a fresh one.
func (a *Authenticator) Login() error {
	a.lock.Lock()
	defer a.lock.Unlock()

	err := a.ensureInitialized()
	if err != nil {
		return err
	}

	// Remove any cached tokens to trigger full relogin.
	if err := a.purgeCredentialsCacheLocked(); err != nil {
		return err
	}

	if !a.baseToken.provider.RequiresInteraction() {
		return nil // can mint the token on the fly, no need for login
	}

	// Create an initial base token. This may require interaction with a user. Do
	// not do retries here, since Login is called when the user is looking, let
	// the user do the retries (since if MintToken() interacts with the user,
	// retrying it automatically will be extra confusing).
	a.baseToken.token, err = a.baseToken.provider.MintToken(a.ctx, nil)
	if err != nil {
		return err
	}

	// Store the initial token in the cache. Don't abort if it fails, the token
	// is still usable from the memory.
	if err := a.baseToken.putToCache(a.ctx); err != nil {
		logging.Warningf(a.ctx, "Failed to write token to cache: %s", err)
	}

	return nil
}

// PurgeCredentialsCache removes cached tokens.
//
// Does not revoke them!
func (a *Authenticator) PurgeCredentialsCache() error {
	a.lock.Lock()
	defer a.lock.Unlock()
	if err := a.ensureInitialized(); err != nil {
		return err
	}
	return a.purgeCredentialsCacheLocked()
}

func (a *Authenticator) purgeCredentialsCacheLocked() error {
	// No need to purge twice if baseToken == authToken, which is the case in
	// non-actor mode.
	var merr errors.MultiError
	if a.baseToken != a.authToken {
		merr = errors.NewMultiError(
			a.baseToken.purgeToken(a.ctx),
			a.authToken.purgeToken(a.ctx))
	} else {
		merr = errors.NewMultiError(a.baseToken.purgeToken(a.ctx))
	}

	switch total, first := merr.Summary(); {
	case total == 0:
		return nil
	case total == 1:
		return first
	default:
		return merr
	}
}

////////////////////////////////////////////////////////////////////////////////
// credentials.PerRPCCredentials implementation.

type perRPCCreds struct {
	a *Authenticator
}

func (creds perRPCCreds) GetRequestMetadata(c context.Context, uri ...string) (map[string]string, error) {
	if len(uri) == 0 {
		panic("perRPCCreds: no URI given")
	}
	if creds.a == nil {
		return nil, nil
	}
	tok, err := creds.a.GetAccessToken(creds.a.opts.MinTokenLifetime)
	if err != nil {
		return nil, err
	}
	return map[string]string{
		"Authorization": tok.TokenType + " " + tok.AccessToken,
	}, nil
}

func (creds perRPCCreds) RequireTransportSecurity() bool { return true }

////////////////////////////////////////////////////////////////////////////////
// oauth2.TokenSource implementation.

type tokenSource struct {
	a *Authenticator
}

// Token is part of oauth2.TokenSource interface.
func (s tokenSource) Token() (*oauth2.Token, error) {
	return s.a.GetAccessToken(s.a.opts.MinTokenLifetime)
}

////////////////////////////////////////////////////////////////////////////////
// Authenticator private methods.

// actingMode returns possible ways the authenticator can "act" as an account.
type actingMode int

const (
	actingModeNone actingMode = 0
	actingModeIAM  actingMode = 1
	actingModeLUCI actingMode = 2
)

// actingMode returns an acting mode based on Options.
func (a *Authenticator) actingMode() actingMode {
	switch {
	case a.opts.ActAsServiceAccount == "":
		return actingModeNone
	case a.opts.ActViaLUCIRealm != "":
		return actingModeLUCI
	default:
		return actingModeIAM
	}
}

// checkInitialized is (true, <err>) if initialization happened (successfully or
// not) of (false, nil) if not.
func (a *Authenticator) checkInitialized() (bool, error) {
	if a.err != nil || a.baseToken != nil {
		return true, a.err
	}
	return false, nil
}

// ensureInitialized instantiates TokenProvider and reads token from cache.
//
// It is supposed to be called under the lock.
func (a *Authenticator) ensureInitialized() error {
	// Already initialized (successfully or not)?
	if initialized, err := a.checkInitialized(); initialized {
		return err
	}

	// ActViaLUCIRealm makes sense only with ActAsServiceAccount.
	if a.opts.ActViaLUCIRealm != "" && a.opts.ActAsServiceAccount == "" {
		a.err = ErrBadOptions
		return a.err
	}

	// SelectBestMethod may do heavy calls like talking to GCE metadata server,
	// call it lazily here rather than in NewAuthenticator.
	if a.opts.Method == AutoSelectMethod {
		a.opts.Method = SelectBestMethod(a.ctx, *a.opts)
	}

	// In Actor mode, switch the base token to have scopes required to call
	// the API used to generate target auth tokens. In non-actor mode, the base
	// token is also the target auth token, so scope it to whatever scopes were
	// requested via Options.
	var scopes []string
	switch a.actingMode() {
	case actingModeNone:
		scopes = a.opts.Scopes
	case actingModeIAM:
		scopes = []string{OAuthScopeIAM}
	case actingModeLUCI:
		scopes = []string{OAuthScopeEmail}
	default:
		panic("impossible")
	}
	a.baseToken = &tokenWithProvider{}
	a.baseToken.provider, a.err = makeBaseTokenProvider(a.ctx, a.opts, scopes)
	if a.err != nil {
		return a.err // note: this can be ErrInsufficientAccess
	}

	// In non-actor mode, the token we must check in 'CheckLoginRequired' is the
	// same as returned by 'GetAccessToken'. In actor mode, they are different.
	// See comments for 'baseToken' and 'authToken'.
	switch a.actingMode() {
	case actingModeNone:
		a.authToken = a.baseToken
	case actingModeIAM:
		a.authToken = &tokenWithProvider{}
		a.authToken.provider, a.err = makeIAMTokenProvider(a.ctx, a.opts)
	case actingModeLUCI:
		a.authToken = &tokenWithProvider{}
		a.authToken.provider, a.err = makeLUCITokenProvider(a.ctx, a.opts)
	default:
		panic("impossible")
	}
	if a.err != nil {
		return a.err
	}

	// Initialize the token cache. Use the disk cache only if SecretsDir is given
	// and any of the providers is not "lightweight" (so it makes sense to
	// actually hit the disk, rather then call the provider each time new token is
	// needed).
	//
	// Note also that tests set a.testingCache before ensureInitialized() is
	// called to mock the cache. Respect this.
	if a.testingCache != nil {
		a.baseToken.cache = a.testingCache
		a.authToken.cache = a.testingCache
	} else {
		cache := internal.ProcTokenCache
		if !a.baseToken.provider.Lightweight() || !a.authToken.provider.Lightweight() {
			if a.opts.SecretsDir != "" {
				cache = &internal.DiskTokenCache{
					Context:    a.ctx,
					SecretsDir: a.opts.SecretsDir,
				}
			} else {
				logging.Warningf(a.ctx, "Disabling auth disk token cache. Not configured.")
			}
		}
		// Use the disk cache only for non-lightweight providers to avoid
		// unnecessarily leaks of tokens to the disk.
		if a.baseToken.provider.Lightweight() {
			a.baseToken.cache = internal.ProcTokenCache
		} else {
			a.baseToken.cache = cache
		}
		if a.authToken.provider.Lightweight() {
			a.authToken.cache = internal.ProcTokenCache
		} else {
			a.authToken.cache = cache
		}
	}

	// Interactive providers need to know whether there's a cached token (to ask
	// to run interactive login if there's none). Non-interactive providers do not
	// care about state of the cache that much (they know how to update it
	// themselves). So examine the cache here only when using interactive
	// provider. Non interactive providers will do it lazily on a first
	// refreshToken(...) call.
	if a.baseToken.provider.RequiresInteraction() {
		// Broken token cache is not a fatal error. So just log it and forget, a new
		// token will be minted in Login.
		if err := a.baseToken.fetchFromCache(a.ctx); err != nil {
			logging.Warningf(a.ctx, "Failed to read auth token from cache: %s", err)
		}
	}

	// Note: a.authToken.provider is either equal to a.baseToken.provider (if not
	// using actor mode), or (when using actor mode) it doesn't require
	// interaction (because all "acting" providers are non-interactive). So don't
	// bother fetching 'authToken' from the cache. It will be fetched lazily on
	// the first use.

	return nil
}

// doLoginIfRequired optionally performs an interactive login.
//
// This is the main place where LoginMode handling is performed. Used by various
// factories (Transport, PerRPCCredentials, TokenSource, ...).
//
// If requiresAuth is false, we respect OptionalLogin mode. If true - we treat
// OptionalLogin mode as SilentLogin: some authentication mechanisms (like
// oauth2.TokenSource) require valid tokens no matter what. The corresponding
// factories set requiresAuth to true.
//
// Returns:
//   (true, nil) if successfully initialized the authenticator with some token.
//   (false, nil) to disable authentication (for OptionalLogin mode).
//   (false, err) on errors.
func (a *Authenticator) doLoginIfRequired(requiresAuth bool) (useAuth bool, err error) {
	err = a.CheckLoginRequired() // also initializes guts for effectiveLoginMode()
	effectiveMode := a.effectiveLoginMode()
	if requiresAuth && effectiveMode == OptionalLogin {
		effectiveMode = SilentLogin
	}
	switch {
	case err == nil:
		return true, nil // have a valid cached base token
	case err == ErrInsufficientAccess && effectiveMode == OptionalLogin:
		return false, nil // have the base token, but it doesn't have enough scopes
	case err != ErrLoginRequired:
		return false, err // some error we can't handle (we handle only ErrLoginRequired)
	case effectiveMode == SilentLogin:
		return false, ErrLoginRequired // can't run Login in SilentLogin mode
	case effectiveMode == OptionalLogin:
		return false, nil // we can skip auth in OptionalLogin if we have no token
	case effectiveMode != InteractiveLogin:
		return false, fmt.Errorf("invalid mode argument: %s", effectiveMode)
	}
	if err := a.Login(); err != nil {
		return false, err
	}
	return true, nil
}

// effectiveLoginMode returns a login mode to use, considering what kind of a
// token provider is being used.
//
// See comments for OptionalLogin for more info. The gist of it: we treat
// OptionalLogin as SilentLogin when using a service account private key.
func (a *Authenticator) effectiveLoginMode() (lm LoginMode) {
	// a.opts.Method is modified under a lock, need to grab the lock to avoid a
	// race. Note that a.loginMode is immutable and can be read outside the
	// lock. We skip the locking if we know for sure that the return value will be
	// same as a.loginMode (which is the case for a.loginMode != OptionalLogin).
	lm = a.loginMode
	if lm == OptionalLogin {
		a.lock.RLock()
		if a.opts.Method == ServiceAccountMethod {
			lm = SilentLogin
		}
		a.lock.RUnlock()
	}
	return
}

// currentToken returns last known authentication token (or nil).
//
// If the token is not loaded yet, will attempt to load it from the on-disk
// cache. Returns nil if it's not there.
//
// It lock a.lock inside. It MUST NOT be called when a.lock is held. It will
// lazily call 'ensureInitialized' if necessary, returning its error.
func (a *Authenticator) currentToken() (tok *internal.Token, err error) {
	a.lock.RLock()
	initialized, err := a.checkInitialized()
	if initialized && err == nil {
		tok = a.authToken.token
	}
	a.lock.RUnlock()
	if err != nil {
		return
	}

	if !initialized || tok == nil {
		a.lock.Lock()
		defer a.lock.Unlock()

		if !initialized {
			if err = a.ensureInitialized(); err != nil {
				return
			}
			tok = a.authToken.token
		}

		if tok == nil {
			// Reading the token from cache is best effort. A broken cache is treated
			// like a cache miss.
			if cacheErr := a.authToken.fetchFromCache(a.ctx); cacheErr != nil {
				logging.Warningf(a.ctx, "Failed to read auth token from cache: %s", cacheErr)
			}
			tok = a.authToken.token
		}
	}

	return
}

// refreshToken compares current auth token to 'prev' and launches token refresh
// procedure if they still match.
//
// Returns a refreshed token (if a refresh procedure happened) or the current
// token, if it's already different from 'prev'. Acts as "Compare-And-Swap"
// where "Swap" is a token refresh procedure.
//
// If the token can't be refreshed (e.g. the base token or the credentials were
// revoked), sets the current auth token to nil and returns an error.
func (a *Authenticator) refreshToken(prev *internal.Token, lifetime time.Duration) (*internal.Token, error) {
	return a.authToken.compareAndRefresh(a.ctx, compareAndRefreshOp{
		lock:     &a.lock,
		prev:     prev,
		lifetime: lifetime,
		refreshCb: func(ctx context.Context, prev *internal.Token) (*internal.Token, error) {
			// In Actor mode, need to make sure we have a sufficiently fresh base
			// token first, since it's needed to call "acting" API to get a new auth
			// token for the target service account. 1 min should be more than enough
			// to make an RPC.
			var base *internal.Token
			if a.actingMode() != actingModeNone {
				var err error
				if base, err = a.getBaseTokenLocked(ctx, time.Minute); err != nil {
					return nil, err
				}
			}
			return a.authToken.renewToken(ctx, prev, base)
		},
	})
}

// getBaseTokenLocked is used to get an actor token when running in actor mode.
//
// It is called with a.lock locked.
func (a *Authenticator) getBaseTokenLocked(ctx context.Context, lifetime time.Duration) (*internal.Token, error) {
	// Already have a good token?
	if !internal.TokenExpiresInRnd(ctx, a.baseToken.token, lifetime) {
		return a.baseToken.token, nil
	}

	// Need to make one.
	return a.baseToken.compareAndRefresh(ctx, compareAndRefreshOp{
		lock:     nil, // already holding the lock
		prev:     a.baseToken.token,
		lifetime: lifetime,
		refreshCb: func(ctx context.Context, prev *internal.Token) (*internal.Token, error) {
			return a.baseToken.renewToken(ctx, prev, nil)
		},
	})
}

////////////////////////////////////////////////////////////////////////////////
// Transport implementation.

// authTokenInjector injects an authentication token into request headers.
//
// Used as a callback for NewModifyingTransport.
func (a *Authenticator) authTokenInjector(req *http.Request) error {
	switch tok, err := a.GetAccessToken(a.opts.MinTokenLifetime); {
	case err == ErrLoginRequired && a.effectiveLoginMode() == OptionalLogin:
		return nil // skip auth, no need for modifications
	case err != nil:
		return err
	default:
		tok.SetAuthHeader(req)
		return nil
	}
}

////////////////////////////////////////////////////////////////////////////////
// tokenWithProvider implementation.

// tokenWithProvider wraps a token with provider that can update it and a cache
// that stores it.
type tokenWithProvider struct {
	token    *internal.Token        // in-memory cache of the token
	provider internal.TokenProvider // knows how to generate 'token'
	cache    internal.TokenCache    // persistent cache for the token
}

// fetchFromCache updates 't.token' by reading it from the cache.
func (t *tokenWithProvider) fetchFromCache(ctx context.Context) error {
	key, err := t.provider.CacheKey(ctx)
	if err != nil {
		return err
	}
	tok, err := t.cache.GetToken(key)
	if err != nil {
		return err
	}
	t.token = tok
	return nil
}

// putToCache puts 't.token' value into the cache.
func (t *tokenWithProvider) putToCache(ctx context.Context) error {
	key, err := t.provider.CacheKey(ctx)
	if err != nil {
		return err
	}
	return t.cache.PutToken(key, t.token)
}

// purgeToken removes the token from both on-disk cache and memory.
func (t *tokenWithProvider) purgeToken(ctx context.Context) error {
	t.token = nil
	key, err := t.provider.CacheKey(ctx)
	if err != nil {
		return err
	}
	return t.cache.DeleteToken(key)
}

// compareAndRefreshOp is parameters for 'compareAndRefresh' call.
type compareAndRefreshOp struct {
	lock      sync.Locker     // optional lock to grab when comparing and refreshing
	prev      *internal.Token // previously known token (the one we are refreshing)
	lifetime  time.Duration   // minimum acceptable token lifetime or <0 to force a refresh
	refreshCb func(ctx context.Context, existing *internal.Token) (*internal.Token, error)
}

// compareAndRefresh compares currently stored token to 'prev' and calls the
// given callback (under the lock, if not nil) to refresh it if they are still
// equal.
//
// Returns a refreshed token (if a refresh procedure happened) or the current
// token, if it's already different from 'prev'. Acts as "Compare-And-Swap"
// where "Swap" is a token refresh callback.
//
// If the callback returns an error (meaning the token can't be refreshed), sets
// the token to nil and returns the error.
func (t *tokenWithProvider) compareAndRefresh(ctx context.Context, params compareAndRefreshOp) (*internal.Token, error) {
	cacheKey, err := t.provider.CacheKey(ctx)
	if err != nil {
		// An error here is truly fatal. It is something like "can't read service
		// account JSON from disk". There's no way to refresh a token without it.
		return nil, err
	}

	// To give a context to "Minting a new token" messages and similar below.
	ctx = logging.SetFields(ctx, logging.Fields{
		"key":    cacheKey.Key,
		"scopes": strings.Join(cacheKey.Scopes, " "),
	})

	// Check that the token still need a refresh and do it (under the lock).
	tok, cacheIt, err := func() (*internal.Token, bool, error) {
		if params.lock != nil {
			params.lock.Lock()
			defer params.lock.Unlock()
		}

		// Some other goroutine already updated the token, just return the new one.
		if t.token != nil && !internal.EqualTokens(t.token, params.prev) {
			return t.token, false, nil
		}

		// Rescan the cache. Maybe some other process updated the token. This branch
		// is also responsible for lazy-loading of tokens from cache for
		// non-interactive providers, see ensureInitialized().
		if cached, _ := t.cache.GetToken(cacheKey); cached != nil {
			t.token = cached
			if !internal.EqualTokens(cached, params.prev) && params.lifetime > 0 && !internal.TokenExpiresIn(ctx, cached, params.lifetime) {
				return cached, false, nil
			}
		}

		// No one updated the token yet. It should be us. Mint a new token or
		// refresh the existing one.
		start := clock.Now(ctx)
		newTok, err := params.refreshCb(ctx, t.token)
		if err != nil {
			t.token = nil
			return nil, false, err
		}
		now := clock.Now(ctx)
		logging.Debugf(
			ctx, "The token refreshed in %s, expires in %s",
			now.Sub(start), newTok.Expiry.Round(0).Sub(now))
		t.token = newTok
		return newTok, true, nil
	}()

	if err == internal.ErrBadRefreshToken || err == internal.ErrBadCredentials {
		// Do not keep the broken token in the cache. It is unusable. Do this
		// outside the lock to avoid blocking other callers. Note that t.token is
		// already nil.
		if err := t.cache.DeleteToken(cacheKey); err != nil {
			logging.Warningf(ctx, "Failed to remove broken token from the cache: %s", err)
		}
		// A bad refresh token can be fixed by interactive login, so adjust the
		// error accordingly in this case.
		if err == internal.ErrBadRefreshToken {
			err = ErrLoginRequired
		}
	}

	if err != nil {
		return nil, err
	}

	// Update the cache outside the lock, no need for callers to wait for this.
	// Do not die if failed, the token is still usable from the memory.
	if cacheIt && tok != nil {
		if err := t.cache.PutToken(cacheKey, tok); err != nil {
			logging.Warningf(ctx, "Failed to write refreshed token to the cache: %s", err)
		}
	}

	return tok, nil
}

// renewToken is called to mint a new token or update existing one.
//
// It is called from non-interactive 'refreshToken' method, and thus it can't
// use interactive login flow.
func (t *tokenWithProvider) renewToken(ctx context.Context, prev, base *internal.Token) (*internal.Token, error) {
	if prev == nil {
		if t.provider.RequiresInteraction() {
			return nil, ErrLoginRequired
		}
		logging.Debugf(ctx, "Minting a new token")
		tok, err := t.mintTokenWithRetries(ctx, base)
		if err != nil {
			logging.Warningf(ctx, "Failed to mint a token: %s", err)
			return nil, err
		}
		return tok, nil
	}

	logging.Debugf(ctx, "Refreshing the token")
	tok, err := t.refreshTokenWithRetries(ctx, prev, base)
	if err != nil {
		logging.Warningf(ctx, "Failed to refresh the token: %s", err)
		return nil, err
	}
	return tok, nil
}

// retryParams defines retry strategy for handling transient errors when minting
// or refreshing tokens.
func retryParams() retry.Iterator {
	return &retry.ExponentialBackoff{
		Limited: retry.Limited{
			Delay:    100 * time.Millisecond,
			Retries:  50,
			MaxTotal: 30 * time.Second,
		},
		Multiplier: 2,
	}
}

// mintTokenWithRetries calls provider's MintToken() retrying on transient
// errors a bunch of times. Called only for non-interactive providers.
func (t *tokenWithProvider) mintTokenWithRetries(ctx context.Context, base *internal.Token) (tok *internal.Token, err error) {
	err = retry.Retry(ctx, transient.Only(retryParams), func() error {
		tok, err = t.provider.MintToken(ctx, base)
		return err
	}, retry.LogCallback(ctx, "token-mint"))
	return
}

// refreshTokenWithRetries calls providers' RefreshToken(...) retrying on
// transient errors a bunch of times.
func (t *tokenWithProvider) refreshTokenWithRetries(ctx context.Context, prev, base *internal.Token) (tok *internal.Token, err error) {
	err = retry.Retry(ctx, transient.Only(retryParams), func() error {
		tok, err = t.provider.RefreshToken(ctx, prev, base)
		return err
	}, retry.LogCallback(ctx, "token-refresh"))
	return
}

////////////////////////////////////////////////////////////////////////////////
// Utility functions.

// makeBaseTokenProvider creates TokenProvider implementation based on options.
//
// opts.Scopes is ignored, 'scopes' is used instead. This is used in actor mode
// to supply scopes necessary to use an "acting" API.
//
// Called by ensureInitialized.
func makeBaseTokenProvider(ctx context.Context, opts *Options, scopes []string) (internal.TokenProvider, error) {
	if opts.testingBaseTokenProvider != nil {
		return opts.testingBaseTokenProvider, nil
	}

	switch opts.Method {
	case UserCredentialsMethod:
		return internal.NewUserAuthTokenProvider(
			ctx,
			opts.ClientID,
			opts.ClientSecret,
			scopes)
	case ServiceAccountMethod:
		serviceAccountPath := ""
		if len(opts.ServiceAccountJSON) == 0 {
			serviceAccountPath = opts.ServiceAccountJSONPath
		}
		return internal.NewServiceAccountTokenProvider(
			ctx,
			opts.ServiceAccountJSON,
			serviceAccountPath,
			scopes)
	case GCEMetadataMethod:
		return internal.NewGCETokenProvider(ctx, opts.GCEAccountName, scopes)
	case LUCIContextMethod:
		return internal.NewLUCIContextTokenProvider(ctx, scopes, opts.Transport)
	default:
		return nil, fmt.Errorf("auth: unrecognized authentication method: %s", opts.Method)
	}
}

// makeIAMTokenProvider creates TokenProvider to use in actingModeIAM mode.
//
// Called by ensureInitialized.
func makeIAMTokenProvider(ctx context.Context, opts *Options) (internal.TokenProvider, error) {
	if opts.testingIAMTokenProvider != nil {
		return opts.testingIAMTokenProvider, nil
	}
	return internal.NewIAMTokenProvider(
		ctx,
		opts.ActAsServiceAccount,
		opts.Scopes,
		opts.Transport)
}

// makeLUCITokenProvider creates TokenProvider to use in actingModeLUCI mode.
//
// Called by ensureInitialized.
func makeLUCITokenProvider(ctx context.Context, opts *Options) (internal.TokenProvider, error) {
	if opts.TokenServerHost == "" {
		return nil, ErrBadOptions
	}
	if internal.NewLUCITSTokenProvider == nil {
		return nil, errors.New("support for impersonation through LUCI is not compiled into this binary")
	}
	return internal.NewLUCITSTokenProvider(
		ctx,
		opts.TokenServerHost,
		opts.ActAsServiceAccount,
		opts.ActViaLUCIRealm,
		opts.Scopes,
		opts.Transport)
}
