diff --git a/Sources/XXMessengerClient/Utils/AuthCallbacksRegistry.swift b/Sources/XXMessengerClient/Utils/AuthCallbacksRegistry.swift
new file mode 100644
index 0000000000000000000000000000000000000000..dfe8bce2ceadaa31788df33812c267f0330e3bcc
--- /dev/null
+++ b/Sources/XXMessengerClient/Utils/AuthCallbacksRegistry.swift
@@ -0,0 +1,36 @@
+import XXClient
+import XCTestDynamicOverlay
+import Foundation
+
+public struct AuthCallbacksRegistry {
+  public var register: (AuthCallbacks) -> Cancellable
+  public var registered: () -> AuthCallbacks
+}
+
+extension AuthCallbacksRegistry {
+  public static func live() -> AuthCallbacksRegistry {
+    class Registry {
+      var authCallbacks: [UUID: AuthCallbacks] = [:]
+    }
+    let registry = Registry()
+    return AuthCallbacksRegistry(
+      register: { authCallbacks in
+        let id = UUID()
+        registry.authCallbacks[id] = authCallbacks
+        return Cancellable { registry.authCallbacks[id] = nil }
+      },
+      registered: {
+        AuthCallbacks { callback in
+          registry.authCallbacks.values.forEach { $0.handle(callback) }
+        }
+      }
+    )
+  }
+}
+
+extension AuthCallbacksRegistry {
+  public static let unimplemented = AuthCallbacksRegistry(
+    register: XCTUnimplemented("\(Self.self)", placeholder: Cancellable {}),
+    registered: XCTUnimplemented("\(Self.self)", placeholder: AuthCallbacks { _ in })
+  )
+}
diff --git a/Tests/XXMessengerClientTests/TestHelpers/AuthCallback.Callback+stubs.swift b/Tests/XXMessengerClientTests/TestHelpers/AuthCallback.Callback+stubs.swift
new file mode 100644
index 0000000000000000000000000000000000000000..9617c0b21319cb7d5624e0bcd3a6b22fbff3bc69
--- /dev/null
+++ b/Tests/XXMessengerClientTests/TestHelpers/AuthCallback.Callback+stubs.swift
@@ -0,0 +1,24 @@
+import XXClient
+
+extension Array where Element == AuthCallbacks.Callback {
+  static let stubs: [AuthCallbacks.Callback] = [
+    .confirm(
+      contact: "contact-1".data(using: .utf8)!,
+      receptionId: "reception-id-1".data(using: .utf8)!,
+      ephemeralId: 1,
+      roundId: 1
+    ),
+    .request(
+      contact: "contact-2".data(using: .utf8)!,
+      receptionId: "reception-id-2".data(using: .utf8)!,
+      ephemeralId: 2,
+      roundId: 2
+    ),
+    .reset(
+      contact: "contact-3".data(using: .utf8)!,
+      receptionId: "reception-id-3".data(using: .utf8)!,
+      ephemeralId: 3,
+      roundId: 3
+    ),
+  ]
+}
diff --git a/Tests/XXMessengerClientTests/Utils/AuthCallbacksRegistryTests.swift b/Tests/XXMessengerClientTests/Utils/AuthCallbacksRegistryTests.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1d1ba7b2f6226e9283fc60d8656dbe0b317113a1
--- /dev/null
+++ b/Tests/XXMessengerClientTests/Utils/AuthCallbacksRegistryTests.swift
@@ -0,0 +1,43 @@
+import XCTest
+import XXClient
+@testable import XXMessengerClient
+import CustomDump
+
+final class AuthCallbacksRegistryTests: XCTestCase {
+  func testRegistry() {
+    var firstAuthCallbacksDidHandle: [AuthCallbacks.Callback] = []
+    var secondAuthCallbacksDidHandle: [AuthCallbacks.Callback] = []
+
+    let firstAuthCallbacks = AuthCallbacks { callback in
+      firstAuthCallbacksDidHandle.append(callback)
+    }
+    let secondAuthCallbacks = AuthCallbacks { callback in
+      secondAuthCallbacksDidHandle.append(callback)
+    }
+    let messengerAuthCallbacks: AuthCallbacksRegistry = .live()
+    let registeredAuthCallbacks = messengerAuthCallbacks.registered()
+    let firstAuthCallbacksCancellable = messengerAuthCallbacks.register(firstAuthCallbacks)
+    let secondAuthCallbacksCancellable = messengerAuthCallbacks.register(secondAuthCallbacks)
+
+    let firstCallback = [AuthCallbacks.Callback].stubs[0]
+    registeredAuthCallbacks.handle(firstCallback)
+
+    XCTAssertNoDifference(firstAuthCallbacksDidHandle, [firstCallback])
+    XCTAssertNoDifference(secondAuthCallbacksDidHandle, [firstCallback])
+
+    firstAuthCallbacksCancellable.cancel()
+    let secondCallback = [AuthCallbacks.Callback].stubs[1]
+    registeredAuthCallbacks.handle(secondCallback)
+
+    XCTAssertNoDifference(firstAuthCallbacksDidHandle, [firstCallback])
+    XCTAssertNoDifference(secondAuthCallbacksDidHandle, [firstCallback, secondCallback])
+
+    secondAuthCallbacksCancellable.cancel()
+
+    let thirdCallback = [AuthCallbacks.Callback].stubs[2]
+    registeredAuthCallbacks.handle(thirdCallback)
+
+    XCTAssertNoDifference(firstAuthCallbacksDidHandle, [firstCallback])
+    XCTAssertNoDifference(secondAuthCallbacksDidHandle, [firstCallback, secondCallback])
+  }
+}