Authenticate Users - Swift SDK
On this page
Log In
Anonymous User
If you have enabled Anonymous authentication in the App Services UI, users can immediately log into your app without providing any identifying information. The following code shows how to do this:
let anonymousCredentials = Credentials.anonymous app.login(credentials: anonymousCredentials) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
Email/Password User
If you have enabled Email/Password authentication, you can log in using the following code:
let email = "skroob@example.com" let password = "12345" app.login(credentials: Credentials.emailPassword(email: email, password: password)) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
API Key User
If you have enabled API Key authentication, you can log in using the following code:
let credentials = Credentials.userAPIKey("<api-key>") app.login(credentials: credentials) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
Custom Function User
If you have enabled the Custom Function authentication provider, you can log in using the following code:
let params: Document = ["username": "bob"] app.login(credentials: Credentials.function(payload: params)) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
Custom JWT User
If you have enabled the Custom JWT authentication provider, you can log in using the following code:
let credentials = Credentials.jwt(token: "<jwt>") app.login(credentials: credentials) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
Facebook User
The Facebook authentication provider allows you to authenticate users through a Facebook app using their existing Facebook account.
Important
Enable the Facebook Auth Provider
To log a user in with their existing Facebook account, you must configure and enable the Facebook authentication provider for your application.
Important
Do Not Store Facebook Profile Picture URLs
Facebook profile picture URLs include the user's access token to grant permission to the image. To ensure security, do not store a URL that includes a user's access token. Instead, access the URL directly from the user's metadata fields when you need to fetch the image.
Follow the official Facebook Login for iOS Quickstart to set up the authentication flow for your application. In the login completion handler, create an App Services Facebook credential with the logged in user's access token string and log the user into your App Services app.
// This example demonstrates login logic for FBSDK version 13.x. If you're using // a different version of FBSDK, you'll need to adapt this example for your version. let loginManager = LoginManager() loginManager.logIn(permissions: [ .email ]) { loginResult in switch loginResult { case .success(let grantedPermissions, let declinedPermissions, let accessToken): let credentials = Credentials.facebook(accessToken: accessToken!.tokenString) app.login(credentials: credentials) { result in DispatchQueue.main.async { switch result { case .failure(let error): print("Failed to log in to MongoDB Realm: \(error)") case .success(let user): print("Successfully logged in to MongoDB Realm using Facebook OAuth.") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } } } case .failed(let error): print("Facebook login failed: \(error)") case .cancelled: print("The user cancelled the login flow.") } }
Google User
Important
To log a user in with their existing Google account, you must configure and enable the Google authentication provider for your application.
Follow the official Google Sign-In for iOS Integration Guide to set up the authentication flow for your application. In the sign-in completion handler, create an App Services Google credential and log the user into your App Services app.
The value that you pass to the credential depends on whether or not you have enabled OpenID Connect for the provider:
If OpenID Connect is enabled, pass the
id_token
included in the Google OAuth response to Credentials.googleId(token:).If OpenID Connect is not enabled, pass the user's server auth code to Credentials.google(serverAuthCode:).
func sign(_ signIn: GIDSignIn!, didSignInFor googleUser: GIDGoogleUser!, withError error: Error!) { if let error = error { print("\(error.localizedDescription)") return } // Get the ID token for the authenticated user so you can pass it to Realm let idToken = googleUser.authentication.idToken! let credentials = Credentials.googleId(token: idToken) app.login(credentials: credentials) { result in DispatchQueue.main.async { switch result { case .failure(let error): print("Failed to log in to MongoDB Realm: \(error)") case .success(let user): print("Successfully logged in to MongoDB Realm using Google OAuth.") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } } } }
func sign(_ signIn: GIDSignIn!, didSignInFor googleUser: GIDGoogleUser!, withError error: Error!) { if let error = error { print("\(error.localizedDescription)") return } // Upon first successful sign-in, forward serverAuthCode credentials to MongoDB Realm. // Upon subsequent sign-ins, this returns nil. let credentials = Credentials.google(serverAuthCode: googleUser.serverAuthCode!) app.login(credentials: credentials) { result in DispatchQueue.main.async { switch result { case .failure(let error): print("Failed to log in to MongoDB Realm: \(error)") case .success(let user): print("Successfully logged in to MongoDB Realm using Google OAuth.") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } } } }
Apple User
If you have enabled Sign-in with Apple authentication, you can log in using the following code:
// Fetch IDToken via the Apple SDK let credentials = Credentials.apple(idToken: "<token>") app.login(credentials: credentials) { (result) in switch result { case .failure(let error): print("Login failed: \(error.localizedDescription)") case .success(let user): print("Successfully logged in as user \(user)") // Now logged in, do something with user // Remember to dispatch to main if you are doing anything on the UI thread } }
Tip
If you get a Login failed
error saying that the token contains
an invalid number of segments
, verify that you're passing a UTF-8-encoded
string version of the JWT.
Async/Await Login
New in version 10.15.0.
The async/await version of the App.login method asynchronously returns a User or Error.
func login() async { do { let app = App(id: YOUR_APP_SERVICES_APP_ID) // Authenticate with the instance of the app that points // to your backend. Here, we're using anonymous login. let user = try await app.login(credentials: Credentials.anonymous) print("Successfully logged in user: \(user)") } catch { print("Failed to log in 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.
Offline Login
When your Realm application authenticates a user, it caches the user's credentials. You can check for existing user credentials to bypass the login flow and access the cached user. Use this to open a realm offline.
Note
Initial login requires a network connection
When a user signs up for your app, or logs in for the first time with an existing account on a client, the client must have a network connection. Checking for cached user credentials lets you open a realm offline, but only if the user has previously logged in while online.
// Log the user into the backend app. // The first time you login, the user must have a network connection. func getUser() async throws -> User { // Check for an existing user. // If the user is offline but credentials are // cached, this returns the existing user. if let user = app.currentUser { return user } else { // If the device has no cached user // credentials, log them in. let app = App(id: YOUR_APP_SERVICES_APP_ID) let loggedInUser = try await app.login(credentials: Credentials.anonymous) return loggedInUser } } let user = try await getUser() var configuration = user.configuration(partitionValue: "Some Partition Value") // Open a Realm with this configuration. // If you do not require the app to download updates // before opening the realm, the realm just opens, even if // offline. let realm = try await Realm(configuration: configuration) print("Successfully opened realm: \(realm)")
Get a User Access Token
The Realm SDK automatically manages access tokens, refreshes them when they expire, and includes a valid access token for the current user with each request.
If you send requests outside of the SDK, you must include the user's access token with each request. In this scenario, you must manually refresh the token when it expires. Access tokens expire after 30 minutes.
You can call .refreshCustomData()
on a logged-in user to refresh the user's auth session. Then, return the
.accessToken
as a string you can use in your code. You might use a
function similar to this to fetch an access token:
func getValidAccessToken(user: User) async throws -> String { // An already logged in user's access token might be stale. To // guarantee that the token is valid, refresh it if necessary. try await user.refreshCustomData() return user.accessToken! }
Which requires a logged-in user:
let app = App(id: YOUR_APP_SERVICES_APP_ID) let user = try await app.login(credentials: Credentials.anonymous) let accessToken = try await getValidAccessToken(user: user)
Refresh Token Expiration
Refresh tokens expire after a set period of time. When the refresh token expires, the access token can no longer be refreshed and the user must log in again.
If the refresh token expires after the realm is open, the device will not be able to sync until the user logs in again. Your sync error handler should implement logic that catches a token expired error when attempting to sync, then redirect users to a login flow.
For information on configuring refresh token expiration, refer to Manage User Sessions in the App Services documentation.
Log Out
Once logged in, you can log out:
Warning
When a user logs out, you can no longer read or write data in any synced realms that the user opened. As a result, any operation that has not yet completed before the initiating user logs out cannot complete successfully and will likely result in an error. Any data in a write operation that fails in this way will be lost.
app.currentUser?.logOut { (error) in // user is logged out or there was an error }