Link User Identities - Swift SDK
On this page
Overview
Atlas App Services provides many authentication providers to log users into your app. Each provider creates a unique user identity. App Services and the Realm Swift SDK lets you merge multiple credentials into one user identity.
Example
Consider an application that offers anonymous login. This allows users to explore the app without
registering. If users like the application, they create permanent
accounts. They sign up with SSO or email/password authentication. By default,
this creates a new User
object. The app must link the new
identity with the original User.
You can link identities using linkUser(credentials:Credentials)
. This
links authentication providers to a logged-in User
object.
@interface LinkIdentitiesExample : NSObject @end @implementation LinkIdentitiesExample { RLMApp *app; RLMUser *anonymousUser; } // Entry-point for example. - (void)runExample { app = [RLMApp appWithId:YOUR_APP_ID]; [self logInAnonymously]; } - (void)logInAnonymously { [app loginWithCredential:[RLMCredentials anonymousCredentials] completion:^(RLMUser *user, NSError *error) { if (error != nil) { NSLog(@"Failed to log in: %@", [error localizedDescription]); return; } // User uses app, then later registers an account [self registerNewAccountAsAnonymousUser: user]; }]; } - (void)registerNewAccountAsAnonymousUser:(RLMUser *)user { NSString *email = @"link2@example.com"; NSString *password = @"ganondorf"; [[app emailPasswordAuth] registerUserWithEmail:email password:password completion:^(NSError *error) { if (error != nil) { NSLog(@"Failed to register new account: %@", [error localizedDescription]); return; } // Successfully created account, now link it // with the existing anon user [self linkUser:self->anonymousUser withCredentials:[RLMCredentials credentialsWithEmail:email password:password]]; }]; } - (void)linkUser:(RLMUser *)user withCredentials:(RLMCredentials *)credentials { [[app currentUser] linkUserWithCredentials:credentials completion:^(RLMUser *user, NSError *error) { if (error != nil) { NSLog(@"Failed to link user: %@", [error localizedDescription]); return; } NSLog(@"Successfully linked user: %@", user); }]; } @end
let app = App(id: YOUR_APP_SERVICES_APP_ID) func logInAnonymously() { app.login(credentials: Credentials.anonymous) { (result) in switch result { case .failure(let error): print("Failed to log in: \(error.localizedDescription)") case .success(let user): // User uses app, then later registers an account registerNewAccount(anonymousUser: user) } } } func registerNewAccount(anonymousUser: User) { let email = "swift-link@example.com" let password = "ganondorf" app.emailPasswordAuth.registerUser(email: email, password: password) { (error) in guard error == nil else { print("Failed to register new account: \(error!.localizedDescription)") return } // Successfully created account, now link it // with the existing anon user link(user: anonymousUser, with: Credentials.emailPassword(email: email, password: password)) } } func link(user: User, with credentials: Credentials) { user.linkUser(credentials: credentials) { (result) in switch result { case .failure(let error): print("Failed to link user: \(error.localizedDescription)") case .success(let user): print("Successfully linked user: \(user)") } } } logInAnonymously()
Async/Await Example
New in version 10.16.0.
The Realm Swift SDK provides an async/await version of User.linkUser.
let app = App(id: YOUR_APP_SERVICES_APP_ID) func logInAnonymously() async throws -> User { let anonymousUser = try await app.login(credentials: Credentials.anonymous) // User uses app, then later registers an account let newAccountLinkedUser = try await registerNewAccount(anonymousUser: anonymousUser) return newAccountLinkedUser } func registerNewAccount(anonymousUser: User) async throws -> User { let email = "swift-async-link@example.com" let password = "ganondorf" try await app.emailPasswordAuth.registerUser(email: email, password: password) // Successfully created account, now link it // with the existing anon user let linkedUser = try await link(user: anonymousUser, with: Credentials.emailPassword(email: email, password: password)) return linkedUser } func link(user: User, with credentials: Credentials) async throws -> User { try await user.linkUser(credentials: credentials) } do { let linkedUser = try await logInAnonymously() print("Successfully linked user async: \(linkedUser)") } catch { print("Failed to link user: \(error.localizedDescription)") }
Starting with Realm Swift SDK Versions 10.15.0 and 10.16.0, many of the Realm APIs support the Swift async/await syntax. Projects must meet these requirements:
Swift SDK Version | Swift Version Requirement | Supported OS |
---|---|---|
10.25.0 | Swift 5.6 | iOS 13.x |
10.15.0 or 10.16.0 | Swift 5.5 | iOS 15.x |
If your app accesses Realm in an async/await
context, mark the code
with @MainActor
to avoid threading-related crashes.