diff --git a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
index 4092af826336f082c259e6f062ba40d86380852b..c45c93ef4fb5b3f3f7052d1b99aa15c1b038709b 100644
--- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
@@ -16,6 +16,12 @@ extension AppEnvironment {
     let dbManager = DBManager.live()
     let messengerEnv = MessengerEnvironment.live()
     let messenger = Messenger.live(messengerEnv)
+    let authHandler = AuthCallbackHandler.live(
+      messenger: messenger,
+      handleRequest: .live(db: dbManager.getDB, now: Date.init),
+      handleConfirm: .live(db: dbManager.getDB),
+      handleReset: .live(db: dbManager.getDB)
+    )
     let mainQueue = DispatchQueue.main.eraseToAnyScheduler()
     let bgQueue = DispatchQueue.global(qos: .background).eraseToAnyScheduler()
 
@@ -53,9 +59,9 @@ extension AppEnvironment {
         HomeEnvironment(
           messenger: messenger,
           dbManager: dbManager,
+          authHandler: authHandler,
           mainQueue: mainQueue,
           bgQueue: bgQueue,
-          now: Date.init,
           register: {
             RegisterEnvironment(
               messenger: messenger,
diff --git a/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift b/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift
index 985ef3293ca3abdab70532f0d40f99676a1b29fb..e28008f39e924af1c5816bb33c9e4dce11798476 100644
--- a/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift
+++ b/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift
@@ -14,6 +14,7 @@ import XXModels
 public struct HomeState: Equatable {
   public init(
     failure: String? = nil,
+    authFailure: String? = nil,
     isNetworkHealthy: Bool? = nil,
     networkNodesReport: NodeRegistrationReport? = nil,
     isDeletingAccount: Bool = false,
@@ -23,6 +24,7 @@ public struct HomeState: Equatable {
     userSearch: UserSearchState? = nil
   ) {
     self.failure = failure
+    self.authFailure = authFailure
     self.isNetworkHealthy = isNetworkHealthy
     self.isDeletingAccount = isDeletingAccount
     self.alert = alert
@@ -32,6 +34,7 @@ public struct HomeState: Equatable {
   }
 
   public var failure: String?
+  public var authFailure: String?
   public var isNetworkHealthy: Bool?
   public var networkNodesReport: NodeRegistrationReport?
   public var isDeletingAccount: Bool
@@ -49,10 +52,11 @@ public enum HomeAction: Equatable {
     case failure(NSError)
   }
 
-  public enum AuthCallbacks: Equatable {
-    case register
-    case unregister
-    case handle(XXClient.AuthCallbacks.Callback)
+  public enum AuthHandler: Equatable {
+    case start
+    case stop
+    case failure(NSError)
+    case failureDismissed
   }
 
   public enum NetworkMonitor: Equatable {
@@ -70,7 +74,7 @@ public enum HomeAction: Equatable {
   }
 
   case messenger(Messenger)
-  case authCallbacks(AuthCallbacks)
+  case authHandler(AuthHandler)
   case networkMonitor(NetworkMonitor)
   case deleteAccount(DeleteAccount)
   case didDismissAlert
@@ -88,18 +92,18 @@ public struct HomeEnvironment {
   public init(
     messenger: Messenger,
     dbManager: DBManager,
+    authHandler: AuthCallbackHandler,
     mainQueue: AnySchedulerOf<DispatchQueue>,
     bgQueue: AnySchedulerOf<DispatchQueue>,
-    now: @escaping () -> Date,
     register: @escaping () -> RegisterEnvironment,
     contacts: @escaping () -> ContactsEnvironment,
     userSearch: @escaping () -> UserSearchEnvironment
   ) {
     self.messenger = messenger
     self.dbManager = dbManager
+    self.authHandler = authHandler
     self.mainQueue = mainQueue
     self.bgQueue = bgQueue
-    self.now = now
     self.register = register
     self.contacts = contacts
     self.userSearch = userSearch
@@ -107,9 +111,9 @@ public struct HomeEnvironment {
 
   public var messenger: Messenger
   public var dbManager: DBManager
+  public var authHandler: AuthCallbackHandler
   public var mainQueue: AnySchedulerOf<DispatchQueue>
   public var bgQueue: AnySchedulerOf<DispatchQueue>
-  public var now: () -> Date
   public var register: () -> RegisterEnvironment
   public var contacts: () -> ContactsEnvironment
   public var userSearch: () -> UserSearchEnvironment
@@ -119,9 +123,9 @@ extension HomeEnvironment {
   public static let unimplemented = HomeEnvironment(
     messenger: .unimplemented,
     dbManager: .unimplemented,
+    authHandler: .unimplemented,
     mainQueue: .unimplemented,
     bgQueue: .unimplemented,
-    now: XCTUnimplemented("\(Self.self).now", placeholder: Date()),
     register: { .unimplemented },
     contacts: { .unimplemented },
     userSearch: { .unimplemented }
@@ -137,7 +141,7 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
   switch action {
   case .messenger(.start):
     return .merge(
-      Effect(value: .authCallbacks(.register)),
+      Effect(value: .authHandler(.start)),
       Effect(value: .networkMonitor(.stop)),
       Effect.result {
         do {
@@ -175,12 +179,11 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
     state.failure = error.localizedDescription
     return .none
 
-  case .authCallbacks(.register):
+  case .authHandler(.start):
     return Effect.run { subscriber in
-      let handler = AuthCallbacks { callback in
-        subscriber.send(.authCallbacks(.handle(callback)))
-      }
-      let cancellable = env.messenger.registerAuthCallbacks(handler)
+      let cancellable = env.authHandler(onError: { error in
+        subscriber.send(.authHandler(.failure(error as NSError)))
+      })
       return AnyCancellable { cancellable.cancel() }
     }
     .subscribe(on: env.bgQueue)
@@ -188,44 +191,15 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
     .eraseToEffect()
     .cancellable(id: AuthCallbacksEffectId.self, cancelInFlight: true)
 
-  case .authCallbacks(.unregister):
+  case .authHandler(.stop):
     return .cancel(id: AuthCallbacksEffectId.self)
 
-  case .authCallbacks(.handle(.request(let contact, _, _, _))):
-    return .fireAndForget {
-      let db = try env.dbManager.getDB()
-      let contactId = try contact.getId()
-      guard try db.fetchContacts(.init(id: [contactId])).isEmpty else {
-        return
-      }
-      var dbContact = XXModels.Contact(id: contactId)
-      dbContact.marshaled = contact.data
-      dbContact.username = try contact.getFact(.username)?.value
-      dbContact.email = try contact.getFact(.email)?.value
-      dbContact.phone = try contact.getFact(.phone)?.value
-      dbContact.authStatus = .verificationInProgress
-      dbContact.createdAt = env.now()
-      dbContact = try db.saveContact(dbContact)
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
-
-  case .authCallbacks(.handle(.confirm(let contact, _, _, _))):
-    return .fireAndForget {
-      let db = try env.dbManager.getDB()
-      let contactId = try contact.getId()
-      guard var dbContact = try db.fetchContacts(.init(id: [contactId])).first else {
-        return
-      }
-      dbContact.authStatus = .friend
-      dbContact = try db.saveContact(dbContact)
-    }
-    .subscribe(on: env.bgQueue)
-    .receive(on: env.mainQueue)
-    .eraseToEffect()
+  case .authHandler(.failure(let error)):
+    state.authFailure = error.localizedDescription
+    return .none
 
-  case .authCallbacks(.handle(.reset(let contact, _, _, _))):
+  case .authHandler(.failureDismissed):
+    state.authFailure = nil
     return .none
 
   case .networkMonitor(.start):
diff --git a/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift b/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift
index f1abfb2b9ebf3d4b2ad4d20aa477b2f49d96fb80..f6a964896e6e67544e693d83cb26378756414b86 100644
--- a/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift
+++ b/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift
@@ -15,12 +15,14 @@ public struct HomeView: View {
 
   struct ViewState: Equatable {
     var failure: String?
+    var authFailure: String?
     var isNetworkHealthy: Bool?
     var networkNodesReport: NodeRegistrationReport?
     var isDeletingAccount: Bool
 
     init(state: HomeState) {
       failure = state.failure
+      authFailure = state.authFailure
       isNetworkHealthy = state.isNetworkHealthy
       isDeletingAccount = state.isDeletingAccount
       networkNodesReport = state.networkNodesReport
@@ -31,21 +33,32 @@ public struct HomeView: View {
     WithViewStore(store, observe: ViewState.init) { viewStore in
       NavigationView {
         Form {
-          Section {
-            if let failure = viewStore.failure {
+          if let failure = viewStore.failure {
+            Section {
               Text(failure)
               Button {
                 viewStore.send(.messenger(.start))
               } label: {
                 Text("Retry")
               }
-            }
-          } header: {
-            if viewStore.failure != nil {
+            } header: {
               Text("Error")
             }
           }
 
+          if let authFailure = viewStore.authFailure {
+            Section {
+              Text(authFailure)
+              Button {
+                viewStore.send(.authHandler(.failureDismissed))
+              } label: {
+                Text("Dismiss")
+              }
+            } header: {
+              Text("Auth Error")
+            }
+          }
+
           Section {
             HStack {
               Text("Health")
diff --git a/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift b/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift
index 40cd5a2a7e2fbf4cd586b667d5c2aa9e36392db2..f3e5bcf8f787e963820b4a33cd09cb31f4494fd5 100644
--- a/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift
@@ -1,3 +1,4 @@
+import AppCore
 import ComposableArchitecture
 import ContactsFeature
 import RegisterFeature
@@ -21,7 +22,7 @@ final class HomeFeatureTests: XCTestCase {
 
     store.environment.bgQueue = .immediate
     store.environment.mainQueue = .immediate
-    store.environment.messenger.registerAuthCallbacks.run = { _ in Cancellable {} }
+    store.environment.authHandler.run = { _ in Cancellable {} }
     store.environment.messenger.start.run = { messengerDidStartWithTimeout.append($0) }
     store.environment.messenger.isConnected.run = { false }
     store.environment.messenger.connect.run = { messengerDidConnect += 1 }
@@ -33,13 +34,13 @@ final class HomeFeatureTests: XCTestCase {
     XCTAssertNoDifference(messengerDidStartWithTimeout, [30_000])
     XCTAssertNoDifference(messengerDidConnect, 1)
 
-    store.receive(.authCallbacks(.register))
+    store.receive(.authHandler(.start))
     store.receive(.networkMonitor(.stop))
     store.receive(.messenger(.didStartUnregistered)) {
       $0.register = RegisterState()
     }
 
-    store.send(.authCallbacks(.unregister))
+    store.send(.authHandler(.stop))
   }
 
   func testMessengerStartRegistered() {
@@ -55,7 +56,7 @@ final class HomeFeatureTests: XCTestCase {
 
     store.environment.bgQueue = .immediate
     store.environment.mainQueue = .immediate
-    store.environment.messenger.registerAuthCallbacks.run = { _ in Cancellable {} }
+    store.environment.authHandler.run = { _ in Cancellable {} }
     store.environment.messenger.start.run = { messengerDidStartWithTimeout.append($0) }
     store.environment.messenger.isConnected.run = { false }
     store.environment.messenger.connect.run = { messengerDidConnect += 1 }
@@ -78,14 +79,13 @@ final class HomeFeatureTests: XCTestCase {
     XCTAssertNoDifference(messengerDidConnect, 1)
     XCTAssertNoDifference(messengerDidLogIn, 1)
 
-    store.receive(.authCallbacks(.register))
+    store.receive(.authHandler(.start))
     store.receive(.networkMonitor(.stop))
     store.receive(.messenger(.didStartRegistered))
     store.receive(.networkMonitor(.start))
 
     store.send(.networkMonitor(.stop))
-
-    store.send(.authCallbacks(.unregister))
+    store.send(.authHandler(.stop))
   }
 
   func testRegisterFinished() {
@@ -102,7 +102,7 @@ final class HomeFeatureTests: XCTestCase {
 
     store.environment.bgQueue = .immediate
     store.environment.mainQueue = .immediate
-    store.environment.messenger.registerAuthCallbacks.run = { _ in Cancellable {} }
+    store.environment.authHandler.run = { _ in Cancellable {} }
     store.environment.messenger.start.run = { messengerDidStartWithTimeout.append($0) }
     store.environment.messenger.isConnected.run = { true }
     store.environment.messenger.isLoggedIn.run = { false }
@@ -127,14 +127,13 @@ final class HomeFeatureTests: XCTestCase {
     XCTAssertNoDifference(messengerDidStartWithTimeout, [30_000])
     XCTAssertNoDifference(messengerDidLogIn, 1)
 
-    store.receive(.authCallbacks(.register))
+    store.receive(.authHandler(.start))
     store.receive(.networkMonitor(.stop))
     store.receive(.messenger(.didStartRegistered))
     store.receive(.networkMonitor(.start))
 
     store.send(.networkMonitor(.stop))
-
-    store.send(.authCallbacks(.unregister))
+    store.send(.authHandler(.stop))
   }
 
   func testMessengerStartFailure() {
@@ -149,18 +148,18 @@ final class HomeFeatureTests: XCTestCase {
 
     store.environment.bgQueue = .immediate
     store.environment.mainQueue = .immediate
-    store.environment.messenger.registerAuthCallbacks.run = { _ in Cancellable {} }
+    store.environment.authHandler.run = { _ in Cancellable {} }
     store.environment.messenger.start.run = { _ in throw error }
 
     store.send(.messenger(.start))
 
-    store.receive(.authCallbacks(.register))
+    store.receive(.authHandler(.start))
     store.receive(.networkMonitor(.stop))
     store.receive(.messenger(.failure(error as NSError))) {
       $0.failure = error.localizedDescription
     }
 
-    store.send(.authCallbacks(.unregister))
+    store.send(.authHandler(.stop))
   }
 
   func testMessengerStartConnectFailure() {
@@ -175,20 +174,20 @@ final class HomeFeatureTests: XCTestCase {
 
     store.environment.bgQueue = .immediate
     store.environment.mainQueue = .immediate
-    store.environment.messenger.registerAuthCallbacks.run = { _ in Cancellable {} }
+    store.environment.authHandler.run = { _ in Cancellable {} }
     store.environment.messenger.start.run = { _ in }
     store.environment.messenger.isConnected.run = { false }
     store.environment.messenger.connect.run = { throw error }
 
     store.send(.messenger(.start))
 
-    store.receive(.authCallbacks(.register))
+    store.receive(.authHandler(.start))
     store.receive(.networkMonitor(.stop))
     store.receive(.messenger(.failure(error as NSError))) {
       $0.failure = error.localizedDescription
     }
 
-    store.send(.authCallbacks(.unregister))
+    store.send(.authHandler(.stop))
   }
 
   func testMessengerStartIsRegisteredFailure() {
@@ -203,7 +202,7 @@ final class HomeFeatureTests: XCTestCase {
 
     store.environment.bgQueue = .immediate
     store.environment.mainQueue = .immediate
-    store.environment.messenger.registerAuthCallbacks.run = { _ in Cancellable {} }
+    store.environment.authHandler.run = { _ in Cancellable {} }
     store.environment.messenger.start.run = { _ in }
     store.environment.messenger.isConnected.run = { true }
     store.environment.messenger.isLoggedIn.run = { false }
@@ -211,13 +210,13 @@ final class HomeFeatureTests: XCTestCase {
 
     store.send(.messenger(.start))
 
-    store.receive(.authCallbacks(.register))
+    store.receive(.authHandler(.start))
     store.receive(.networkMonitor(.stop))
     store.receive(.messenger(.failure(error as NSError))) {
       $0.failure = error.localizedDescription
     }
 
-    store.send(.authCallbacks(.unregister))
+    store.send(.authHandler(.stop))
   }
 
   func testMessengerStartLogInFailure() {
@@ -232,7 +231,7 @@ final class HomeFeatureTests: XCTestCase {
 
     store.environment.bgQueue = .immediate
     store.environment.mainQueue = .immediate
-    store.environment.messenger.registerAuthCallbacks.run = { _ in Cancellable {} }
+    store.environment.authHandler.run = { _ in Cancellable {} }
     store.environment.messenger.start.run = { _ in }
     store.environment.messenger.isConnected.run = { true }
     store.environment.messenger.isLoggedIn.run = { false }
@@ -241,13 +240,13 @@ final class HomeFeatureTests: XCTestCase {
 
     store.send(.messenger(.start))
 
-    store.receive(.authCallbacks(.register))
+    store.receive(.authHandler(.start))
     store.receive(.networkMonitor(.stop))
     store.receive(.messenger(.failure(error as NSError))) {
       $0.failure = error.localizedDescription
     }
 
-    store.send(.authCallbacks(.unregister))
+    store.send(.authHandler(.stop))
   }
 
   func testNetworkMonitorStart() {
@@ -527,101 +526,37 @@ final class HomeFeatureTests: XCTestCase {
       environment: .unimplemented
     )
 
-    let now = Date()
-    var didRegisterCallbacks: [AuthCallbacks] = []
-    var didCancelAuthCallbacks = 0
-    var dbContact: XXModels.Contact?
-    var dbDidSaveContact: [XXModels.Contact] = []
+    var didRunAuthHandler = 0
+    var didCancelAuthHandler = 0
+    var authHandlerOnError: [AuthCallbackHandler.OnError] = []
 
     store.environment.mainQueue = .immediate
     store.environment.bgQueue = .immediate
-    store.environment.now = { now }
-    store.environment.messenger.registerAuthCallbacks.run = { callbacks in
-      didRegisterCallbacks.append(callbacks)
-      return Cancellable { didCancelAuthCallbacks += 1 }
-    }
-    store.environment.dbManager.getDB.run = {
-      var db: Database = .failing
-      db.fetchContacts.run = { _ in [dbContact].compactMap { $0 } }
-      db.saveContact.run = { contact in
-        dbDidSaveContact.append(contact)
-        return contact
-      }
-      return db
-    }
-
-    store.send(.authCallbacks(.register))
-
-    XCTAssertNoDifference(didRegisterCallbacks.count, 1)
-
-    var contact = XXClient.Contact.unimplemented("data".data(using: .utf8)!)
-    contact.getIdFromContact.run = { _ in "id".data(using: .utf8)! }
-    contact.getFactsFromContact.run = { _ in
-      [
-        Fact(type: .username, value: "username"),
-        Fact(type: .email, value: "email"),
-        Fact(type: .phone, value: "phone"),
-      ]
+    store.environment.authHandler.run = { onError in
+      didRunAuthHandler += 1
+      authHandlerOnError.append(onError)
+      return Cancellable { didCancelAuthHandler += 1 }
     }
 
-    dbContact = nil
-    dbDidSaveContact = []
-    didRegisterCallbacks.first?.handle(
-      .request(contact: contact, receptionId: Data(), ephemeralId: 0, roundId: 0)
-    )
+    store.send(.authHandler(.start))
 
-    store.receive(.authCallbacks(.handle(
-      .request(contact: contact, receptionId: Data(), ephemeralId: 0, roundId: 0)
-    )))
-    XCTAssertNoDifference(dbDidSaveContact, [.init(
-      id: "id".data(using: .utf8)!,
-      marshaled: "data".data(using: .utf8)!,
-      username: "username",
-      email: "email",
-      phone: "phone",
-      authStatus: .verificationInProgress,
-      createdAt: now
-    )])
-
-    dbContact = .init(id: "id".data(using: .utf8)!)
-    dbDidSaveContact = []
-    didRegisterCallbacks.first?.handle(
-      .request(contact: contact, receptionId: Data(), ephemeralId: 0, roundId: 0)
-    )
+    XCTAssertNoDifference(didRunAuthHandler, 1)
 
-    store.receive(.authCallbacks(.handle(
-      .request(contact: contact, receptionId: Data(), ephemeralId: 0, roundId: 0)
-    )))
-    XCTAssertNoDifference(dbDidSaveContact, [])
+    struct AuthHandlerError: Error { var id: Int }
+    authHandlerOnError.first?(AuthHandlerError(id: 1))
 
-    dbContact = .init(id: "id".data(using: .utf8)!)
-    dbDidSaveContact = []
-    didRegisterCallbacks.first?.handle(
-      .confirm(contact: contact, receptionId: Data(), ephemeralId: 0, roundId: 0)
-    )
+    store.receive(.authHandler(.failure(AuthHandlerError(id: 1) as NSError))) {
+      $0.authFailure = AuthHandlerError(id: 1).localizedDescription
+    }
 
-    store.receive(.authCallbacks(.handle(
-      .confirm(contact: contact, receptionId: Data(), ephemeralId: 0, roundId: 0)
-    )))
-    XCTAssertNoDifference(dbDidSaveContact, [.init(
-      id: "id".data(using: .utf8)!,
-      authStatus: .friend,
-      createdAt: dbContact!.createdAt
-    )])
-
-    dbContact = nil
-    dbDidSaveContact = []
-    didRegisterCallbacks.first?.handle(
-      .reset(contact: contact, receptionId: Data(), ephemeralId: 0, roundId: 0)
-    )
+    store.send(.authHandler(.failureDismissed)) {
+      $0.authFailure = nil
+    }
 
-    store.receive(.authCallbacks(.handle(
-      .reset(contact: contact, receptionId: Data(), ephemeralId: 0, roundId: 0)
-    )))
-    XCTAssertNoDifference(dbDidSaveContact, [])
+    store.send(.authHandler(.stop))
 
-    store.send(.authCallbacks(.unregister))
+    XCTAssertNoDifference(didCancelAuthHandler, 1)
 
-    XCTAssertNoDifference(didCancelAuthCallbacks, 1)
+    authHandlerOnError.first?(AuthHandlerError(id: 2))
   }
 }