Docs Menu
Docs Home
/ /
Atlas Device SDKs
/ /

Authenticate Users - Swift SDK

On this page

  • Log In
  • Anonymous User
  • Email/Password User
  • API Key User
  • Custom Function User
  • Custom JWT User
  • Facebook User
  • Google User
  • Apple User
  • Async/Await Login
  • Offline Login
  • Get a User Access Token
  • Refresh Token Expiration
  • Log Out

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
}
}

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
}
}

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
}
}

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
}
}

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
}
}

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.")
}
}

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
}
}
}
}

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.

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.

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)")

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 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.

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
}

Back

Create and Delete Users

Next

Custom User Data