code: 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
  	}
  
  	// 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
  }
docs: // 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.