diff --git a/ud/alternate.go b/ud/alternate.go
index f53281c43470d44ed24b40f65a02c143c8d785e3..4f0013bfc77b53278de23012abe7e8d4fe7c876a 100644
--- a/ud/alternate.go
+++ b/ud/alternate.go
@@ -16,12 +16,12 @@ type alternateUd struct {
 	dhPubKey []byte
 }
 
-// SetAlternativeUserDiscovery sets the alternativeUd object within manager.
+// setAlternateUserDiscovery sets the alternativeUd object within manager.
 // Once set, any user discovery operation will go through the alternative
 // user discovery service.
 //
 // To undo this operation, use UnsetAlternativeUserDiscovery.
-func (m *Manager) SetAlternativeUserDiscovery(altCert, altAddress,
+func (m *Manager) setAlternateUserDiscovery(altCert, altAddress,
 	contactFile []byte) error {
 	params := connect.GetDefaultHostParams()
 	params.AuthEnabled = false
@@ -54,6 +54,9 @@ func (m *Manager) SetAlternativeUserDiscovery(altCert, altAddress,
 
 // UnsetAlternativeUserDiscovery clears out the information from
 // the Manager object.
+// fixme: I think this should be removed to avoid creating a Manager object
+//  which has never been registered to production, and can't be w/o exporting
+//  the Manger.register method.
 func (m *Manager) UnsetAlternativeUserDiscovery() error {
 	if m.alternativeUd == nil {
 		return errors.New("Alternative User Discovery is already unset.")
diff --git a/ud/manager.go b/ud/manager.go
index 845d2b800d86170b19a1954a1530bff639617d52..c1d51d00202bef9847220bcfd19376724e898378 100644
--- a/ud/manager.go
+++ b/ud/manager.go
@@ -1,7 +1,6 @@
 package ud
 
 import (
-	"fmt"
 	"gitlab.com/elixxir/crypto/fastRNG"
 	"sync"
 	"time"
@@ -59,54 +58,18 @@ func LoadOrNewManager(user udE2e, comms Comms, follower udNetworkStatus,
 	username string, networkValidationSig []byte) (*Manager, error) {
 	jww.INFO.Println("ud.LoadOrNewManager()")
 
-	if follower() != xxdk.Running {
-		return nil, errors.New(
-			"cannot start UD Manager when network follower is not running.")
-	}
-
-	// Initialize manager
-	m := &Manager{
-		user:  user,
-		comms: comms,
-	}
-
-	if m.isRegistered() {
-		// Load manager if already registered
-		var err error
-		m.store, err = store.NewOrLoadStore(m.getKv())
-		if err != nil {
-			return nil, errors.Errorf("Failed to initialize store: %v", err)
-		}
-		return m, nil
-	}
-
-	// Initialize store
-	var err error
-	m.store, err = store.NewOrLoadStore(m.getKv())
-	if err != nil {
-		return nil, errors.Errorf("Failed to initialize store: %v", err)
-	}
-
-	// Initialize/Get host
-	udHost, err := m.getOrAddUdHost()
+	// Construct manager
+	m, err := loadOrNewManager(user, comms, follower)
 	if err != nil {
-		return nil, errors.WithMessage(err, "User Discovery host object could "+
-			"not be constructed.")
+		return nil, err
 	}
 
-	// Register with user discovery
-	stream := m.getRng().GetStream()
-	defer stream.Close()
-	err = m.register(username, networkValidationSig, stream, m.comms, udHost)
+	// Register manager
+	rng := m.getRng().GetStream()
+	defer rng.Close()
+	err = m.register(username, networkValidationSig, rng, comms)
 	if err != nil {
-		return nil, errors.Errorf("Failed to register: %v", err)
-	}
-
-	// Set storage to registered
-	if err = setRegistered(m.getKv()); err != nil && m.getEventReporter() != nil {
-		m.getEventReporter().Report(1, "UserDiscovery", "Registration",
-			fmt.Sprintf("User Registered with UD: %+v",
-				username))
+		return nil, err
 	}
 
 	return m, nil
@@ -161,6 +124,55 @@ func NewManagerFromBackup(user udE2e, comms Comms, follower udNetworkStatus,
 	return m, nil
 }
 
+// LoadOrNewAlternateUserDiscovery loads an existing Manager from storage or creates a
+// new one if there is no extant storage information. This is different from LoadOrNewManager
+// in that it allows the user to provide alternate User Discovery contact information.
+// These parameters may be used to contact a separate UD server than the one run by the
+// xx network team, one the user or a third-party may operate.
+//
+// Params
+//  - user is an interface that adheres to the xxdk.E2e object.
+//  - comms is an interface that adheres to client.Comms object.
+//  - follower is a method off of xxdk.Cmix which returns the network follower's status.
+//  - username is the name of the user as it is registered with UD. This will be what the end user
+//  provides if through the bindings.
+//  - networkValidationSig is a signature provided by the network (i.e. the client registrar). This may
+//  be nil, however UD may return an error in some cases (e.g. in a production level environment).
+//  - altCert is the TLS certificate for the alternate UD server.
+//  - altAddress is the IP address of the alternate UD server.
+//  - marshalledContact is the data within a marshalled contact.Contact.
+//
+// Returns
+//  - A Manager object which is registered to the specified alternate UD service.
+func LoadOrNewAlternateUserDiscovery(user udE2e, comms Comms, follower udNetworkStatus,
+	username string, networkValidationSig []byte, altCert, altAddress,
+	marshalledContact []byte) (*Manager, error) {
+
+	jww.INFO.Println("ud.LoadOrNewAlternateUserDiscovery()")
+
+	// Construct manager
+	m, err := loadOrNewManager(user, comms, follower)
+	if err != nil {
+		return nil, err
+	}
+
+	// Set alternative user discovery
+	err = m.setAlternateUserDiscovery(altCert, altAddress, marshalledContact)
+	if err != nil {
+		return nil, err
+	}
+
+	// Register manager
+	rng := m.getRng().GetStream()
+	defer rng.Close()
+	err = m.register(username, networkValidationSig, rng, comms)
+	if err != nil {
+		return nil, err
+	}
+
+	return m, nil
+}
+
 // InitStoreFromBackup initializes the UD storage from the backup subsystem.
 func InitStoreFromBackup(kv *versioned.KV,
 	username, email, phone fact.Fact) error {
@@ -291,6 +303,41 @@ func (m *Manager) getOrAddUdHost() (*connect.Host, error) {
 	return host, nil
 }
 
+// loadOrNewManager is a helper function which loads from storage or
+// creates a new Manager object.
+func loadOrNewManager(user udE2e, comms Comms,
+	follower udNetworkStatus) (*Manager, error) {
+	if follower() != xxdk.Running {
+		return nil, errors.New(
+			"cannot start UD Manager when network follower is not running.")
+	}
+
+	// Initialize manager
+	m := &Manager{
+		user:  user,
+		comms: comms,
+	}
+
+	if m.isRegistered() {
+		// Load manager if already registered
+		var err error
+		m.store, err = store.NewOrLoadStore(m.getKv())
+		if err != nil {
+			return nil, errors.Errorf("Failed to initialize store: %v", err)
+		}
+		return m, nil
+	}
+
+	// Initialize store
+	var err error
+	m.store, err = store.NewOrLoadStore(m.getKv())
+	if err != nil {
+		return nil, errors.Errorf("Failed to initialize store: %v", err)
+	}
+
+	return m, nil
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Internal Getters                                                           //
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/ud/manager_test.go b/ud/manager_test.go
index 1bf18a58b4f3aa41915eddecc789c2c1f240fb4f..33a124c0d32f0e7d9a6b92b217a993712415e5d5 100644
--- a/ud/manager_test.go
+++ b/ud/manager_test.go
@@ -53,8 +53,8 @@ func TestManager_SetAlternativeUserDiscovery(t *testing.T) {
 	m, _ := newTestManager(t)
 
 	altAddr := "0.0.0.0:11420"
-	err := m.SetAlternativeUserDiscovery([]byte(testCert), []byte(altAddr), []byte(testContact))
+	err := m.setAlternateUserDiscovery([]byte(testCert), []byte(altAddr), []byte(testContact))
 	if err != nil {
-		t.Fatalf("Unexpected error in SetAlternativeUserDiscovery: %v", err)
+		t.Fatalf("Unexpected error in setAlternateUserDiscovery: %v", err)
 	}
 }
diff --git a/ud/mockE2e_test.go b/ud/mockE2e_test.go
index 28ddaeb0badeab3fd2eb0d18e0cacaba137927e0..c57e148fe6a63845a480bebb1aa939789b600bfc 100644
--- a/ud/mockE2e_test.go
+++ b/ud/mockE2e_test.go
@@ -29,13 +29,14 @@ import (
 ///////////////////////////////////////////////////////////////////////////////
 
 type mockE2e struct {
-	grp     *cyclic.Group
-	events  event.Reporter
-	rng     *fastRNG.StreamGenerator
-	kv      *versioned.KV
-	network cmix.Client
-	t       testing.TB
-	key     *rsa.PrivateKey
+	grp       *cyclic.Group
+	events    event.Reporter
+	rng       *fastRNG.StreamGenerator
+	kv        *versioned.KV
+	network   cmix.Client
+	mockStore mockStorage
+	t         testing.TB
+	key       *rsa.PrivateKey
 }
 
 func (m mockE2e) GetE2E() e2e.Handler {
@@ -89,8 +90,7 @@ func (m mockE2e) GetCmix() cmix.Client {
 }
 
 func (m mockE2e) GetStorage() storage.Session {
-	//TODO implement me
-	panic("implement me")
+	return m.mockStore
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/ud/mockStore_test.go b/ud/mockStore_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..5031f491bbfa8b8f24ca35c9f57d3b5dd6df0575
--- /dev/null
+++ b/ud/mockStore_test.go
@@ -0,0 +1,160 @@
+package ud
+
+import (
+	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/elixxir/client/storage/user"
+	"gitlab.com/elixxir/client/storage/versioned"
+	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/ekv"
+	"gitlab.com/elixxir/primitives/version"
+	"gitlab.com/xx_network/crypto/signature/rsa"
+	"gitlab.com/xx_network/primitives/id"
+	"gitlab.com/xx_network/primitives/ndf"
+	"time"
+)
+
+type mockStorage struct{}
+
+func (m mockStorage) GetKV() *versioned.KV {
+	return versioned.NewKV(ekv.MakeMemstore())
+}
+
+func (m mockStorage) GetClientVersion() version.Version {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) Get(key string) (*versioned.Object, error) {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) Set(key string, object *versioned.Object) error {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) Delete(key string) error {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetCmixGroup() *cyclic.Group {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetE2EGroup() *cyclic.Group {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) ForwardRegistrationStatus(regStatus storage.RegistrationStatus) error {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetRegistrationStatus() storage.RegistrationStatus {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) SetRegCode(regCode string) {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetRegCode() (string, error) {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) SetNDF(def *ndf.NetworkDefinition) {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetNDF() *ndf.NetworkDefinition {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetTransmissionID() *id.ID {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetTransmissionSalt() []byte {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetReceptionID() *id.ID {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetReceptionSalt() []byte {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetReceptionRSA() *rsa.PrivateKey {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetTransmissionRSA() *rsa.PrivateKey {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) IsPrecanned() bool {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) SetUsername(username string) error {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetUsername() (string, error) {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) PortableUserInfo() user.Info {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetTransmissionRegistrationValidationSignature() []byte {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetReceptionRegistrationValidationSignature() []byte {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) GetRegistrationTimestamp() time.Time {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) SetTransmissionRegistrationValidationSignature(b []byte) {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) SetReceptionRegistrationValidationSignature(b []byte) {
+	//TODO implement me
+	panic("implement me")
+}
+
+func (m mockStorage) SetRegistrationTimestamp(tsNano int64) {
+	//TODO implement me
+	panic("implement me")
+}
diff --git a/ud/register.go b/ud/register.go
index f41532bd5605ae7d45ddf90baea152293c489d3e..e59e378c13e4c23cea768eefdc58e0b9136e61bb 100644
--- a/ud/register.go
+++ b/ud/register.go
@@ -1,13 +1,13 @@
 package ud
 
 import (
+	"fmt"
 	"github.com/pkg/errors"
 	pb "gitlab.com/elixxir/comms/mixmessages"
 	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/crypto/factID"
 	"gitlab.com/elixxir/crypto/hash"
 	"gitlab.com/elixxir/primitives/fact"
-	"gitlab.com/xx_network/comms/connect"
 	"gitlab.com/xx_network/crypto/csprng"
 	"gitlab.com/xx_network/crypto/signature/rsa"
 )
@@ -15,9 +15,17 @@ import (
 // register initiates registration with user discovery given a specified
 // username. Provided a comms sub-interface to facilitate testing.
 func (m *Manager) register(username string, networkSignature []byte,
-	rng csprng.Source, comm registerUserComms, udHost *connect.Host) error {
+	rng csprng.Source, comm registerUserComms) error {
 
-	var err error
+	// Initialize/Get host
+	udHost, err := m.getOrAddUdHost()
+	if err != nil {
+		return errors.WithMessage(err,
+			"User Discovery host object could "+
+				"not be constructed.")
+	}
+
+	// Retrieve data used for registration
 	identity := m.user.GetReceptionIdentity()
 	privKey, err := identity.GetRSAPrivatePem()
 	if err != nil {
@@ -63,6 +71,9 @@ func (m *Manager) register(username string, networkSignature []byte,
 	// Hash and sign fact
 	hashedFact := factID.Fingerprint(usernameFact)
 	signedFact, err := rsa.Sign(rng, privKey, hash.CMixHash, hashedFact, nil)
+	if err != nil {
+		return errors.Errorf("Failed to sign fact: %v", err)
+	}
 
 	// Add username fact register request to the user registration message
 	msg.Frs = &pb.FactRegisterRequest{
@@ -76,5 +87,16 @@ func (m *Manager) register(username string, networkSignature []byte,
 
 	// Register user with user discovery
 	_, err = comm.SendRegisterUser(udHost, msg)
+	if err != nil {
+		return err
+	}
+
+	// Set storage to registered
+	if err = setRegistered(m.getKv()); err != nil && m.getEventReporter() != nil {
+		m.getEventReporter().Report(1, "UserDiscovery", "Registration",
+			fmt.Sprintf("User Registered with UD: %+v",
+				username))
+	}
+
 	return err
 }
diff --git a/ud/register_test.go b/ud/register_test.go
index 3a521042c31d8703e752efd439a1456ce8b789af..f5c4f57828f27826ebd025354bc91a13cb81ec49 100644
--- a/ud/register_test.go
+++ b/ud/register_test.go
@@ -26,17 +26,12 @@ func (t *testRegisterComm) SendRegisterUser(_ *connect.Host, msg *pb.UDBUserRegi
 func TestManager_register(t *testing.T) {
 	m, _ := newTestManager(t)
 
-	udHost, err := m.getOrAddUdHost()
-	if err != nil {
-		t.Fatalf("Failed to get/add ud host: %+v", err)
-	}
-
 	c := &testRegisterComm{}
 	prng := NewPrng(42)
 
 	mockSig := []byte("mock")
 
-	err = m.register("testUser", mockSig, prng, c, udHost)
+	err := m.register("testUser", mockSig, prng, c)
 	if err != nil {
 		t.Errorf("register() returned an error: %+v", err)
 	}