code: 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:
  		if !metadata.OnGCE() {
  			logging.Errorf(ctx, "Attempting to use GCE VM service account, but not running on GCE")
  			return nil, ErrBadCredentials
  		}
  		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)
  	}
  }
docs: ////////////////////////////////////////////////////////////////////////////////
  // Utility functions.
  // makeBaseTokenProvider creates TokenProvider implementation based on options.
  //
  // opts.Scopes is ignored, 'scopes' is used instead. This is used in actor mode
  // to substitute scopes with IAM scope.
  //
  // Called by ensureInitialized.