diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4b3c4ccd7f..480c86c09a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,22 @@ x.y.z Release notes (yyyy-MM-dd)
 ### Enhancements
 * None.
 
+### Breaking Changes
+* Change the following methods on RLMUser to properties:
+  - `[RLMUser emailPasswordAuth]` => `RLMUser.emailPasswordAuth`
+  - `[RLMUser identities]` => `RLMUser.identities`
+  - `[RLMUser allSessions]` => `RLMUser.allSessions`
+  - `[RLMUser apiKeysAuth]` => `RLMUser.apiKeysAuth`
+
+* Other changes to RLMUser:
+  - `nullable` has been removed from `RLMUser.identifier`
+  - `nullable` has been removed from `RLMUser.customData`
+
+* Change the following methods on RLMApp to properties:
+  - `[RLMApp allUsers]` => `RLMApp.allUsers`
+  - `[RLMApp currentUser]` => `RLMApp.currentUser`
+  - `[RLMApp emailPasswordAuth]` => `RLMApp.emailPasswordAuth`
+
 ### Fixed
 * <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-cocoa/issues/????), since v?.?.?)
 * None.
diff --git a/Realm/ObjectServerTests/SwiftObjectServerTests.swift b/Realm/ObjectServerTests/SwiftObjectServerTests.swift
index a926d34022..193d6970bb 100644
--- a/Realm/ObjectServerTests/SwiftObjectServerTests.swift
+++ b/Realm/ObjectServerTests/SwiftObjectServerTests.swift
@@ -720,10 +720,10 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
     func testAppInit() {
         let appWithNoConfig = App(id: appName)
-        XCTAssertEqual(appWithNoConfig.allUsers().count, 0)
+        XCTAssertEqual(appWithNoConfig.allUsers.count, 0)
 
         let appWithConfig = App(id: appName, configuration: appConfig())
-        XCTAssertEqual(appWithConfig.allUsers().count, 0)
+        XCTAssertEqual(appWithConfig.allUsers.count, 0)
     }
 
     func testAppLogin() {
@@ -733,7 +733,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let registerUserEx = expectation(description: "Register user")
 
-        app.emailPasswordAuth().registerUser(email: email, password: password) { (error) in
+        app.emailPasswordAuth.registerUser(email: email, password: password) { (error) in
             XCTAssertNil(error)
             registerUserEx.fulfill()
         }
@@ -750,8 +750,8 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         wait(for: [loginEx], timeout: 4.0)
 
-        XCTAssertEqual(syncUser?.id, app.currentUser()?.id)
-        XCTAssertEqual(app.allUsers().count, 1)
+        XCTAssertEqual(syncUser?.id, app.currentUser?.id)
+        XCTAssertEqual(app.allUsers.count, 1)
     }
 
     func testAppSwitchAndRemove() {
@@ -764,12 +764,12 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         let registerUser1Ex = expectation(description: "Register user 1")
         let registerUser2Ex = expectation(description: "Register user 2")
 
-        app.emailPasswordAuth().registerUser(email: email1, password: password1) { (error) in
+        app.emailPasswordAuth.registerUser(email: email1, password: password1) { (error) in
             XCTAssertNil(error)
             registerUser1Ex.fulfill()
         }
 
-        app.emailPasswordAuth().registerUser(email: email2, password: password2) { (error) in
+        app.emailPasswordAuth.registerUser(email: email2, password: password2) { (error) in
             XCTAssertNil(error)
             registerUser2Ex.fulfill()
         }
@@ -798,12 +798,12 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         wait(for: [login2Ex], timeout: 4.0)
 
-        XCTAssertEqual(app.allUsers().count, 2)
+        XCTAssertEqual(app.allUsers.count, 2)
 
-        XCTAssertEqual(syncUser2!.id, app.currentUser()!.id)
+        XCTAssertEqual(syncUser2!.id, app.currentUser!.id)
 
         app.switch(to: syncUser1!)
-        XCTAssertTrue(syncUser1!.id == app.currentUser()?.id)
+        XCTAssertTrue(syncUser1!.id == app.currentUser?.id)
 
         let removeEx = expectation(description: "Remove user 1")
 
@@ -814,8 +814,8 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         wait(for: [removeEx], timeout: 4.0)
 
-        XCTAssertEqual(syncUser2!.id, app.currentUser()!.id)
-        XCTAssertEqual(app.allUsers().count, 1)
+        XCTAssertEqual(syncUser2!.id, app.currentUser!.id)
+        XCTAssertEqual(app.allUsers.count, 1)
     }
 
     func testAppLinkUser() {
@@ -825,7 +825,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let registerUserEx = expectation(description: "Register user")
 
-        app.emailPasswordAuth().registerUser(email: email, password: password) { (error) in
+        app.emailPasswordAuth.registerUser(email: email, password: password) { (error) in
             XCTAssertNil(error)
             registerUserEx.fulfill()
         }
@@ -854,8 +854,8 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         wait(for: [linkEx], timeout: 4.0)
 
-        XCTAssertEqual(syncUser?.id, app.currentUser()?.id)
-        XCTAssertEqual(syncUser?.identities().count, 2)
+        XCTAssertEqual(syncUser?.id, app.currentUser?.id)
+        XCTAssertEqual(syncUser?.identities.count, 2)
     }
 
     // MARK: - Provider Clients
@@ -867,7 +867,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let registerUserEx = expectation(description: "Register user")
 
-        app.emailPasswordAuth().registerUser(email: email, password: password) { (error) in
+        app.emailPasswordAuth.registerUser(email: email, password: password) { (error) in
             XCTAssertNil(error)
             registerUserEx.fulfill()
         }
@@ -875,7 +875,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let confirmUserEx = expectation(description: "Confirm user")
 
-        app.emailPasswordAuth().confirmUser("atoken", tokenId: "atokenid") { (error) in
+        app.emailPasswordAuth.confirmUser("atoken", tokenId: "atokenid") { (error) in
             XCTAssertNotNil(error)
             confirmUserEx.fulfill()
         }
@@ -883,7 +883,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let resendEmailEx = expectation(description: "Resend email confirmation")
 
-        app.emailPasswordAuth().resendConfirmationEmail("atoken") { (error) in
+        app.emailPasswordAuth.resendConfirmationEmail("atoken") { (error) in
             XCTAssertNotNil(error)
             resendEmailEx.fulfill()
         }
@@ -891,7 +891,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let resendResetPasswordEx = expectation(description: "Resend reset password email")
 
-        app.emailPasswordAuth().sendResetPasswordEmail("atoken") { (error) in
+        app.emailPasswordAuth.sendResetPasswordEmail("atoken") { (error) in
             XCTAssertNotNil(error)
             resendResetPasswordEx.fulfill()
         }
@@ -899,14 +899,14 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let resetPasswordEx = expectation(description: "Reset password email")
 
-        app.emailPasswordAuth().resetPassword(to: "password", token: "atoken", tokenId: "tokenId") { (error) in
+        app.emailPasswordAuth.resetPassword(to: "password", token: "atoken", tokenId: "tokenId") { (error) in
             XCTAssertNotNil(error)
             resetPasswordEx.fulfill()
         }
         wait(for: [resetPasswordEx], timeout: 4.0)
 
         let callResetFunctionEx = expectation(description: "Reset password function")
-        app.emailPasswordAuth().callResetPasswordFunction(email: email,
+        app.emailPasswordAuth.callResetPasswordFunction(email: email,
                                                                        password: randomString(10),
                                                                        args: [[:]]) { (error) in
             XCTAssertNotNil(error)
@@ -922,7 +922,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let registerUserEx = expectation(description: "Register user")
 
-        app.emailPasswordAuth().registerUser(email: email, password: password) { (error) in
+        app.emailPasswordAuth.registerUser(email: email, password: password) { (error) in
             XCTAssertNil(error)
             registerUserEx.fulfill()
         }
@@ -943,7 +943,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         let createAPIKeyEx = expectation(description: "Create user api key")
 
         var apiKey: UserAPIKey?
-        syncUser?.apiKeysAuth().createAPIKey(named: "my-api-key") { (key, error) in
+        syncUser?.apiKeysAuth.createAPIKey(named: "my-api-key") { (key, error) in
             XCTAssertNotNil(key)
             XCTAssertNil(error)
             apiKey = key
@@ -952,7 +952,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         wait(for: [createAPIKeyEx], timeout: 4.0)
 
         let fetchAPIKeyEx = expectation(description: "Fetch user api key")
-        syncUser?.apiKeysAuth().fetchAPIKey(apiKey!.objectId) { (key, error) in
+        syncUser?.apiKeysAuth.fetchAPIKey(apiKey!.objectId) { (key, error) in
             XCTAssertNotNil(key)
             XCTAssertNil(error)
             fetchAPIKeyEx.fulfill()
@@ -960,7 +960,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         wait(for: [fetchAPIKeyEx], timeout: 4.0)
 
         let fetchAPIKeysEx = expectation(description: "Fetch user api keys")
-        syncUser?.apiKeysAuth().fetchAPIKeys(completion: { (keys, error) in
+        syncUser?.apiKeysAuth.fetchAPIKeys(completion: { (keys, error) in
             XCTAssertNotNil(keys)
             XCTAssertEqual(keys!.count, 1)
             XCTAssertNil(error)
@@ -969,21 +969,21 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         wait(for: [fetchAPIKeysEx], timeout: 4.0)
 
         let disableKeyEx = expectation(description: "Disable API key")
-        syncUser?.apiKeysAuth().disableAPIKey(apiKey!.objectId) { (error) in
+        syncUser?.apiKeysAuth.disableAPIKey(apiKey!.objectId) { (error) in
             XCTAssertNil(error)
             disableKeyEx.fulfill()
         }
         wait(for: [disableKeyEx], timeout: 4.0)
 
         let enableKeyEx = expectation(description: "Enable API key")
-        syncUser?.apiKeysAuth().enableAPIKey(apiKey!.objectId) { (error) in
+        syncUser?.apiKeysAuth.enableAPIKey(apiKey!.objectId) { (error) in
             XCTAssertNil(error)
             enableKeyEx.fulfill()
         }
         wait(for: [enableKeyEx], timeout: 4.0)
 
         let deleteKeyEx = expectation(description: "Delete API key")
-        syncUser?.apiKeysAuth().deleteAPIKey(apiKey!.objectId) { (error) in
+        syncUser?.apiKeysAuth.deleteAPIKey(apiKey!.objectId) { (error) in
             XCTAssertNil(error)
             deleteKeyEx.fulfill()
         }
@@ -996,7 +996,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let registerUserEx = expectation(description: "Register user")
 
-        app.emailPasswordAuth().registerUser(email: email, password: password) { (error) in
+        app.emailPasswordAuth.registerUser(email: email, password: password) { (error) in
             XCTAssertNil(error)
             registerUserEx.fulfill()
         }
@@ -1038,7 +1038,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let registerUserEx = expectation(description: "Register user")
 
-        app.emailPasswordAuth().registerUser(email: email, password: password) { (error) in
+        app.emailPasswordAuth.registerUser(email: email, password: password) { (error) in
             XCTAssertNil(error)
             registerUserEx.fulfill()
         }
@@ -1055,14 +1055,14 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let registerDeviceExpectation = expectation(description: "Register Device")
         let client = app.pushClient(serviceName: "gcm")
-        client.registerDevice(token: "some-token", user: app.currentUser()!) { error in
+        client.registerDevice(token: "some-token", user: app.currentUser!) { error in
             XCTAssertNil(error)
             registerDeviceExpectation.fulfill()
         }
         wait(for: [registerDeviceExpectation], timeout: 4.0)
 
         let dergisterDeviceExpectation = expectation(description: "Deregister Device")
-        client.deregisterDevice(user: app.currentUser()!, completion: { error in
+        client.deregisterDevice(user: app.currentUser!, completion: { error in
             XCTAssertNil(error)
             dergisterDeviceExpectation.fulfill()
         })
@@ -1075,7 +1075,7 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
 
         let registerUserEx = expectation(description: "Register user")
 
-        app.emailPasswordAuth().registerUser(email: email, password: password) { (error) in
+        app.emailPasswordAuth.registerUser(email: email, password: password) { (error) in
             XCTAssertNil(error)
             registerUserEx.fulfill()
         }
@@ -1108,8 +1108,8 @@ class SwiftObjectServerTests: SwiftSyncTestCase {
         }
         wait(for: [refreshDataEx], timeout: 4.0)
 
-        XCTAssertEqual(app.currentUser()?.customData?["favourite_colour"], .string("green"))
-        XCTAssertEqual(app.currentUser()?.customData?["apples"], .int64(10))
+        XCTAssertEqual(app.currentUser?.customData["favourite_colour"], .string("green"))
+        XCTAssertEqual(app.currentUser?.customData["apples"], .int64(10))
     }
 
     // MARK: - Mongo Client
@@ -2048,7 +2048,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         var cancellable = Set<AnyCancellable>()
 
         let registerUserEx = expectation(description: "Register user")
-        app.emailPasswordAuth().registerUser(email: email, password: password)
+        app.emailPasswordAuth.registerUser(email: email, password: password)
             .sink(receiveCompletion: { result in
                 if case .failure = result {
                     XCTFail("Should register")
@@ -2060,7 +2060,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         wait(for: [registerUserEx], timeout: 4.0)
 
         let confirmUserEx = expectation(description: "Confirm user")
-        app.emailPasswordAuth().confirmUser("atoken", tokenId: "atokenid")
+        app.emailPasswordAuth.confirmUser("atoken", tokenId: "atokenid")
             .sink(receiveCompletion: { result in
                 if case .failure = result {
                     confirmUserEx.fulfill()
@@ -2072,7 +2072,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         wait(for: [confirmUserEx], timeout: 4.0)
 
         let resendEmailEx = expectation(description: "Resend email confirmation")
-        app.emailPasswordAuth().resendConfirmationEmail(email: "atoken")
+        app.emailPasswordAuth.resendConfirmationEmail(email: "atoken")
             .sink(receiveCompletion: { result in
                 if case .failure = result {
                     resendEmailEx.fulfill()
@@ -2084,7 +2084,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         wait(for: [resendEmailEx], timeout: 4.0)
 
         let sendResetPasswordEx = expectation(description: "Send reset password email")
-        app.emailPasswordAuth().sendResetPasswordEmail(email: "atoken")
+        app.emailPasswordAuth.sendResetPasswordEmail(email: "atoken")
             .sink(receiveCompletion: { result in
                 if case .failure = result {
                     sendResetPasswordEx.fulfill()
@@ -2096,7 +2096,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         wait(for: [sendResetPasswordEx], timeout: 4.0)
 
         let resetPasswordEx = expectation(description: "Reset password email")
-        app.emailPasswordAuth().resetPassword(to: "password", token: "atoken", tokenId: "tokenId")
+        app.emailPasswordAuth.resetPassword(to: "password", token: "atoken", tokenId: "tokenId")
             .sink(receiveCompletion: { result in
                 if case .failure = result {
                     resetPasswordEx.fulfill()
@@ -2108,7 +2108,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         wait(for: [resetPasswordEx], timeout: 4.0)
 
         let callResetFunctionEx = expectation(description: "Reset password function")
-        app.emailPasswordAuth().callResetPasswordFunction(email: email, password: randomString(10), args: [[:]])
+        app.emailPasswordAuth.callResetPasswordFunction(email: email, password: randomString(10), args: [[:]])
             .sink(receiveCompletion: { result in
                 if case .failure = result {
                     callResetFunctionEx.fulfill()
@@ -2126,7 +2126,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         let password = randomString(10)
 
         let registerUserEx = expectation(description: "Register user")
-        app.emailPasswordAuth().registerUser(email: email, password: password)
+        app.emailPasswordAuth.registerUser(email: email, password: password)
             .sink(receiveCompletion: { result in
                 if case .failure = result {
                     XCTFail("Should register")
@@ -2145,11 +2145,11 @@ class CombineObjectServerTests: SwiftSyncTestCase {
                 }
             }, receiveValue: { user in
                 loginEx.fulfill()
-                XCTAssertEqual(user.id, self.app.currentUser()?.id)
+                XCTAssertEqual(user.id, self.app.currentUser?.id)
             })
             .store(in: &cancellable)
         wait(for: [loginEx], timeout: 4.0)
-        XCTAssertEqual(self.app.allUsers().count, 1)
+        XCTAssertEqual(self.app.allUsers.count, 1)
     }
 
     func testRefreshCustomDataCombine() {
@@ -2158,7 +2158,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         var cancellable = Set<AnyCancellable>()
 
         let registerUserEx = expectation(description: "Register user")
-        app.emailPasswordAuth().registerUser(email: email, password: password)
+        app.emailPasswordAuth.registerUser(email: email, password: password)
             .sink(receiveCompletion: { result in
                 if case .failure = result {
                     XCTFail("Should register")
@@ -2205,8 +2205,8 @@ class CombineObjectServerTests: SwiftSyncTestCase {
             .store(in: &cancellable)
         wait(for: [refreshDataEx], timeout: 4.0)
 
-        XCTAssertEqual(app.currentUser()?.customData?["favourite_colour"], .string("green"))
-        XCTAssertEqual(app.currentUser()?.customData?["apples"], .int64(10))
+        XCTAssertEqual(app.currentUser?.customData["favourite_colour"], .string("green"))
+        XCTAssertEqual(app.currentUser?.customData["apples"], .int64(10))
     }
 
     func testMongoCollectionInsertCombine() {
@@ -2775,7 +2775,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         var cancellable = Set<AnyCancellable>()
 
         let regEx = expectation(description: "Should register")
-        app.emailPasswordAuth().registerUser(email: email, password: password)
+        app.emailPasswordAuth.registerUser(email: email, password: password)
             .sink(receiveCompletion: { result in
                 if case .failure = result {
                     XCTFail("Should register")
@@ -2843,7 +2843,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         let password = randomString(10)
 
         let registerUserEx = expectation(description: "Register user")
-        app.emailPasswordAuth().registerUser(email: email, password: password)
+        app.emailPasswordAuth.registerUser(email: email, password: password)
             .sink(receiveCompletion: { _ in },
                   receiveValue: { _ in registerUserEx.fulfill() })
             .store(in: &cancellable)
@@ -2862,7 +2862,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
 
         let createAPIKeyEx = expectation(description: "Create user api key")
         var apiKey: UserAPIKey?
-        syncUser?.apiKeysAuth().createAPIKey(named: "my-api-key")
+        syncUser?.apiKeysAuth.createAPIKey(named: "my-api-key")
             .sink(receiveCompletion: { (result) in
                 if case .failure = result {
                     XCTFail("Should create user api key")
@@ -2876,7 +2876,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
 
         let fetchAPIKeyEx = expectation(description: "Fetch user api key")
         var objId: ObjectId? = try? ObjectId(string: apiKey!.objectId.stringValue)
-        syncUser?.apiKeysAuth().fetchAPIKey(objId!)
+        syncUser?.apiKeysAuth.fetchAPIKey(objId!)
             .sink(receiveCompletion: { (result) in
                 if case .failure = result {
                     XCTFail("Should fetch user api key")
@@ -2889,7 +2889,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         wait(for: [fetchAPIKeyEx], timeout: 4.0)
 
         let fetchAPIKeysEx = expectation(description: "Fetch user api keys")
-        syncUser?.apiKeysAuth().fetchAPIKeys()
+        syncUser?.apiKeysAuth.fetchAPIKeys()
             .sink(receiveCompletion: { (result) in
                 if case .failure = result {
                     XCTFail("Should fetch user api keys")
@@ -2903,7 +2903,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
 
         let disableKeyEx = expectation(description: "Disable API key")
         objId = try? ObjectId(string: apiKey!.objectId.stringValue)
-        syncUser?.apiKeysAuth().disableAPIKey(objId!)
+        syncUser?.apiKeysAuth.disableAPIKey(objId!)
             .sink(receiveCompletion: { (result) in
                 if case .failure = result {
                     XCTFail("Should disable user api key")
@@ -2915,7 +2915,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         wait(for: [disableKeyEx], timeout: 4.0)
 
         let enableKeyEx = expectation(description: "Enable API key")
-        syncUser?.apiKeysAuth().enableAPIKey(objId!)
+        syncUser?.apiKeysAuth.enableAPIKey(objId!)
             .sink(receiveCompletion: { (result) in
                 if case .failure = result {
                     XCTFail("Should enable user api key")
@@ -2927,7 +2927,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         wait(for: [enableKeyEx], timeout: 4.0)
 
         let deleteKeyEx = expectation(description: "Delete API key")
-        syncUser?.apiKeysAuth().deleteAPIKey(objId!)
+        syncUser?.apiKeysAuth.deleteAPIKey(objId!)
             .sink(receiveCompletion: { (result) in
                 if case .failure = result {
                     XCTFail("Should delete user api key")
@@ -2945,7 +2945,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         let password = randomString(10)
 
         let registerUserEx = expectation(description: "Register user")
-        app.emailPasswordAuth().registerUser(email: email, password: password)
+        app.emailPasswordAuth.registerUser(email: email, password: password)
             .sink(receiveCompletion: { _ in },
                   receiveValue: { _ in registerUserEx.fulfill() })
             .store(in: &cancellable)
@@ -2960,7 +2960,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
 
         let registerDeviceExpectation = expectation(description: "Register Device")
         let client = app.pushClient(serviceName: "gcm")
-        client.registerDevice(token: "some-token", user: app.currentUser()!)
+        client.registerDevice(token: "some-token", user: app.currentUser!)
             .sink(receiveCompletion: { (result) in
                 if case .failure = result {
                     XCTFail("Should register device")
@@ -2972,7 +2972,7 @@ class CombineObjectServerTests: SwiftSyncTestCase {
         wait(for: [registerDeviceExpectation], timeout: 4.0)
 
         let dergisterDeviceExpectation = expectation(description: "Deregister Device")
-        client.deregisterDevice(user: app.currentUser()!)
+        client.deregisterDevice(user: app.currentUser!)
             .sink(receiveCompletion: { (result) in
                 if case .failure = result {
                     XCTFail("Should deregister device")
diff --git a/Realm/ObjectServerTests/SwiftSyncTestCase.swift b/Realm/ObjectServerTests/SwiftSyncTestCase.swift
index 0e0012e606..f197ed2f72 100644
--- a/Realm/ObjectServerTests/SwiftSyncTestCase.swift
+++ b/Realm/ObjectServerTests/SwiftSyncTestCase.swift
@@ -36,7 +36,7 @@ class SwiftSyncTestCase: RLMSyncTestCase {
         let password = "abcdef"
         let credentials = Credentials(email: username, password: password)
         let ex = expectation(description: "Should register in the user properly")
-        app.emailPasswordAuth().registerUser(email: username, password: password, completion: { error in
+        app.emailPasswordAuth.registerUser(email: username, password: password, completion: { error in
             XCTAssertNil(error)
             ex.fulfill()
         })
diff --git a/Realm/RLMApp.h b/Realm/RLMApp.h
index 4287713ff6..05621cf430 100644
--- a/Realm/RLMApp.h
+++ b/Realm/RLMApp.h
@@ -98,6 +98,20 @@ Create a new Realm App configuration.
 /// The `RLMSyncManager` for this Realm app.
 @property (nonatomic, readonly) RLMSyncManager *syncManager;
 
+/// Get a dictionary containing all users keyed on id.
+@property (nonatomic, readonly) NSDictionary<NSString *, RLMUser *> *allUsers;
+
+/// Get the current user logged into the Realm app.
+@property (nonatomic, readonly, nullable) RLMUser *currentUser;
+
+/**
+  A client for the email/password authentication provider which
+  can be used to obtain a credential for logging in.
+
+  Used to perform requests specifically related to the email/password provider.
+*/
+@property (nonatomic, readonly) RLMEmailPasswordAuth *emailPasswordAuth;
+
 /**
  Get an application with a given appId and configuration.
 
@@ -114,24 +128,6 @@ Create a new Realm App configuration.
 + (instancetype)appWithId:(NSString *)appId
             configuration:(nullable RLMAppConfiguration *)configuration;
 
-/**
- Get a dictionary containing all users keyed on id.
- */
-- (NSDictionary<NSString *, RLMUser *> *)allUsers;
-
-/**
- Get the current user logged into the Realm app.
- */
-- (nullable RLMUser *)currentUser;
-
-/**
-  A client for the email/password authentication provider which
-  can be used to obtain a credential for logging in.
-
-  Used to perform requests specifically related to the email/password provider.
-*/
-- (RLMEmailPasswordAuth *)emailPasswordAuth;
-
 /**
  Login to a user for the Realm app.
 
diff --git a/Realm/RLMUser.h b/Realm/RLMUser.h
index 3a64ec05b1..26a236771e 100644
--- a/Realm/RLMUser.h
+++ b/Realm/RLMUser.h
@@ -66,12 +66,10 @@ NS_ASSUME_NONNULL_BEGIN
  The unique MongoDB Realm string identifying this user.
  Note this is different from an identitiy: A user may have multiple identities but has a single indentifier. See RLMUserIdentity.
  */
-@property (nullable, nonatomic, readonly) NSString *identifier NS_SWIFT_NAME(id);
+@property (nonatomic, readonly) NSString *identifier NS_SWIFT_NAME(id);
 
-/**
- Returns an array of identities currently linked to a user.
-*/
-- (NSArray<RLMUserIdentity *> *)identities;
+/// Returns an array of identities currently linked to a user.
+@property (nonatomic, readonly) NSArray<RLMUserIdentity *> *identities;
 
 /**
  The user's refresh token used to access the Realm Applcation.
@@ -81,7 +79,6 @@ NS_ASSUME_NONNULL_BEGIN
  */
 @property (nullable, nonatomic, readonly) NSString *refreshToken;
 
-
 /**
  The user's refresh token used to access the Realm Application.
 
@@ -118,10 +115,8 @@ NS_ASSUME_NONNULL_BEGIN
  */
 - (nullable RLMSyncSession *)sessionForPartitionValue:(id<RLMBSON>)partitionValue;
 
-/**
- Retrieve all the valid sessions belonging to this user.
- */
-- (NSArray<RLMSyncSession *> *)allSessions;
+/// Retrieve all the valid sessions belonging to this user.
+@property (nonatomic, readonly) NSArray<RLMSyncSession *> *allSessions;
 
 #pragma mark - Custom Data
 
@@ -129,7 +124,7 @@ NS_ASSUME_NONNULL_BEGIN
  The custom data of the user.
  This is configured in your MongoDB Realm App.
  */
-@property (nullable, nonatomic, readonly) NSDictionary *customData NS_REFINED_FOR_SWIFT;
+@property (nonatomic, readonly) NSDictionary *customData NS_REFINED_FOR_SWIFT;
 
 /**
  Refresh a user's custom data. This will, in effect, refresh the user's auth session.
@@ -175,7 +170,7 @@ NS_ASSUME_NONNULL_BEGIN
 
   This client should only be used by an authenticated user.
 */
-- (RLMAPIKeyAuth *)apiKeysAuth;
+@property (nonatomic, readonly) RLMAPIKeyAuth *apiKeysAuth;
 
 /// A client for interacting with a remote MongoDB instance
 /// @param serviceName The name of the MongoDB service
diff --git a/Realm/RLMUser.mm b/Realm/RLMUser.mm
index 632eeb8cfc..7f7c35ff60 100644
--- a/Realm/RLMUser.mm
+++ b/Realm/RLMUser.mm
@@ -129,7 +129,7 @@ - (nullable RLMSyncSession *)sessionForPartitionValue:(id<RLMBSON>)partitionValu
 
 - (NSString *)identifier {
     if (!_user) {
-        return nil;
+        return @"";
     }
     return @(_user->identity().c_str());
 }
@@ -242,14 +242,14 @@ + (void)_setUpBindingContextFactory {
 }
 
 - (NSString *)refreshToken {
-    if (!_user) {
+    if (!_user || _user->refresh_token().empty()) {
         return nil;
     }
     return @(_user->refresh_token().c_str());
 }
 
 - (NSString *)accessToken {
-    if (!_user) {
+    if (!_user || _user->access_token().empty()) {
         return nil;
     }
     return @(_user->access_token().c_str());
@@ -257,7 +257,7 @@ - (NSString *)accessToken {
 
 - (NSDictionary *)customData {
     if (!_user || !_user->custom_data()) {
-        return nil;
+        return @{};
     }
 
     return (NSDictionary *)RLMConvertBsonToRLMBSON(*_user->custom_data());
diff --git a/RealmSwift/Sync.swift b/RealmSwift/Sync.swift
index 62e6a88cce..30499e7952 100644
--- a/RealmSwift/Sync.swift
+++ b/RealmSwift/Sync.swift
@@ -356,11 +356,11 @@ public extension User {
      The custom data of the user.
      This is configured in your MongoDB Realm App.
     */
-    var customData: Document? {
+    var customData: Document {
         guard let rlmCustomData = self.__customData as RLMBSON?,
             let anyBSON = ObjectiveCSupport.convert(object: rlmCustomData),
             case let .document(customData) = anyBSON else {
-            return nil
+            return [:]
         }
 
         return customData