Users

Last updated 22 days ago

Overview

After you have successfully authenticated with your Realm Object Server, you will receive a SyncUser. The central object in the Realm Object Server is the Realm User (SyncUser). The Realm User identifies the application end user, and is used with the server's access control functionality to securely control what data is synchronized.

SyncUsers come in two different types: Regular and Admin. The end users of your application should all be Regular users while Admin users can be used for development and server-side applications. A unique SyncUser will most often represent a unique end user of your application. It is not advised to share a single SyncUser among all of your client applications (i.e. hard-coding auth into your application). When first starting out developing an app with Realm we recommend using an admin account to get the general syncing down and then start using regular users with permissions later.

Working with Users

The Realm Platform allows an application to support multiple users at the same time.

Take, for example, an email client app that supports multiple email accounts. Multiple users (one for each email account) can authenticate at any given time, and the Realm SDKs allows the app to retrieve and open one specific user's Realm(s) without affecting the other email accounts' data or login status.

Swift
Objective-C
Java
Javascript
.Net

The current method will retrieve the current user, the user that logged in most recently and whose credentials have not expired. The method returns nil if there are no active logins (no current user exists). An exception will be thrown if more than one logged-in user exists.

let user = SyncUser.current!

If there are multiple users logged in, you can get a dictionary of user objects corresponding to them with all.

let allUsers = SyncUser.all

The currentUser method will retrieve the current user, the user that logged in most recently and whose credentials have not expired. The method returns nil if no current user exists. An exception will be thrown if more than one logged-in user exists.

RLMSyncUser *user = [RLMSyncUser currentUser];

If there are multiple users logged in, you can get a dictionary of user objects corresponding to them with allUsers.

NSDictionary<NSString *, RLMSyncUser *> *allUsers = [RLMSyncUser allUsers];

If no users are logged in, the dictionary returned will be empty.

The SyncUser.current() method will retrieve the current user, the user that logged in most recently and whose credentials have not expired. The method returns nil if no current user exists. An exception will be thrown if more than one logged-in user exists.

SyncUser user = SyncUser.current();

If there are multiple users logged in, you can get a map between their server identity and their corresponding SyncUser object.

Map<String, SyncUser> users = SyncUser.all();

Realm.Sync.User.current can be used to obtain the user that logged in most recently and whose credentials have not expired. If there are no active user logins, the method will return undefined. If more than one user is logged in, an error will be thrown.

const user = Realm.Sync.User.current;

If there are likely to be multiple users logged in, you can get a collection of them by calling Realm.Sync.User.all. This will be empty if no users have logged in.

let users = Realm.Sync.User.all;
for(const key in users) {
const user = users[key];
// do something with the user object.
}

User.Current will return the currently logged in user. If no users have logged in or all have logged out, it will return null. If there are more than one logged in users, a RealmException will be thrown.

User persistence must be enabled to use this method.

var user = User.Current;

If there are likely to be multiple users logged in, you can get a collection of them by calling User.AllLoggedIn. This will be empty if no users have logged in.

var users = User.AllLoggedIn;
foreach (var user in users)
{
// do something with the user
}

Logging out Users

Logging a user out of the Realm will make them unable to access synchronized realms. If you want to allow access to the local copy of a synced Realm while offline, do not make code your app to Realm logout an automatic process when the application is force quitted.

Swift
Objective-C
Java
Javascript
.Net

To log a user out of their account, call SyncUser.logOut(). Any pending local changes will continue to upload until the Realm Object Server is fully synchronized. The next time the client app is launched, all synced Realms will be deleted from the user's device.

To log a user out of their account, call [RLMSyncUser logOut]. Any pending local changes will continue to upload until the Realm Object Server is fully synchronized. The next time the client app is launched, all synced Realms will be deleted from the user's device.

To log a user out of their account, call SyncUser.logout(). Any pending local changes will continue to uploaded until the Realm Object Server is fully synchronized. The next time the client app is launched, all synced Realms will be deleted from the user's device.

user.logout();

When a user is logs out, any pending local changes will continue to be upload until the Realm Object Server is fully synchronized. The next time the client app is launched, all synced Realms will be deleted locally.

user.LogOut();

When a user is logs out any pending local changes will continue to upload until the Realm Object Server is fully synchronized. The next time the client app is launched, all synced Realms will be deleted locally.

In a situation where multiple users may share the same device (i.e. a tablet that is shared by field workers), it is common to implement some kind of user switch or soft logout functionality. This way you may require a user to authenticate against your own authentication system before reopening the app, but it will not require all of the user's data to be re-synchronized as it will not explicitly call SyncUser.logOut()

Admin Users

Realm Object Server's authentication system has the concept of an admin user. This is a special type which grants the user privileges to:

  • Access any synchronized Realm (including the data within) on the server

  • Login to Realm Studio

In general, these users should be provisioned sparingly and not be given to end users of your application.

Creating an Admin User

Realm Studio

The easiest way to create a new admin user is through Realm Studio. In the Users tab you can select a user then adjust in the dropdown on the side panel if this is an admin user:

You can also define a user as an admin through specific providers:

JWT

With the JWT provider you can include a key in the token payload which defines that the user is an admin. The key is an optional boolean called isAdmin:

const jwt = require('jsonwebtoken');
const fs = require('fs');
const key = fs.readFileSync('private.pem');
const payload = {
userId: '123',
isAdmin: true // optional
// other properties (ignored by Realm Object Server)
};
const token = jwt.sign(payload, { key: key, passphrase: 'your-passphrase' }, { algorithm: 'RS256'});
// Send token to your client app

The JWT provider can also be customized further to determine which inputs determine that a token is an administrator

Cloud
Self-Hosted

You can configure the JWT provider in your instance settings. Adjust the Field Name and Value inputs to control what determines that a token is an administrator:

You can customize the JWT provider through parameters in its constructor within your server start script:

const RealmObjectServer = require('realm-object-server');
const path = require('path');
const server = new RealmObjectServer.BasicServer();
// Add your public key from "Generating RS256 key" section
let jwtProvider = new JWTAuthProvider(
{
publicKey: '-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhki...\n-----END PUBLIC KEY-----',
isAdminFieldName: "isAdmin", // Default is `isAdmin`
isAdminValue: true // Default is `true`
}
)
server.start({
dataPath: path.join(__dirname, '../data'),
authProviders: [ jwtProvider ],
}).catch((err) => {
console.error("There was an error starting your custom Realm Object Server", err);
});

Other Providers

It is possible to create admin users from the other authentication providers as well, but this is typically not recommended for security reasons and as a result is left undocumented. If you believe that you need to create admin users via one of the other providers, please contact us.

The Admin Token

This feature is not available in Realm Cloud.

Admin access is also available via an admin token. This is a self-contained token, similar to a JWT, containing full admin access claims and is signed by the server's private key. The server uses the admin token internally to open up system Realms because it is self-contained and verifiable through the public key, eliminating the need to contact the authentication APIs. As it does not need to use the authentication APIs, this results in slightly improved performance especially for long-running server-side applications that access many Realms (greater than 10k).

For most use-cases, we do not recommend using the admin token since it cannot be easily rotated as it requires the Realm Object Server cluster to be brought down as it is changed. As a result, we recommend creating admin users as described above. If you believe that your usage patterns dictate using the admin token, please contact us to confirm.

The token is generated in the /keys folder in the server's data path, such as /data/keys/admin.json. To retrieve the token in Javascript within the start script of the server:

const adminTokenUser = require(path.resolve(server.config.dataPath, 'keys/admin.json')).ADMIN_TOKEN

This can be used to synchronously construct aRealm.Sync.Userobject which can be passed into theRealmconstructor to open a connection to any Realm on the server side.

// Open a Realm using the admin user
const adminTokenUser = require(path.resolve(server.config.dataPath, 'keys/admin.json')).ADMIN_TOKEN
var adminUser = Realm.Sync.User.adminUser(adminTokenUser, SERVER_URL);
var realm = new Realm({
sync: {
user: adminUser,
url: 'realm://object-server-url:9080/my-realm',
},
schema: [{...}
}]
});

Note that when used with an admin token user, the Realm URL does not include the ~character that resolves into the user ID for non-admin authentication; an admin token user does not have a user ID.

Best Practices

Create a Realm User for Each End User of your Application

When using Realm Sync, every user should be identified by a unique client ID called the userId The userId is a GUID or UUID auto-generated by ROS when it successfully logs in a user. This userId can be overwritten by the developer to define their own userId if needed for administrative purposes - for instance, to match a Realm userId with a user id, such as an email, stored as part of a custom authentication process. It is always recommended to give a unique userId to each sync-client that may sign on and use your app because you may want to identify certain misbehaving users in your system. Even if your app does not require the user to login and create a unique account we still recommend that your app, in user code, logs in with a randomly generated user that occurs in the background of the user using the app; we have created anonymous user explicitly for this purpose.

Limit the Usage of Admin Users

Since Realm admin users have full access to the data in your server, it is never advised to let an end user authenticate as an admin user. Access control is still possible for differentiating users and is properly set via our permissions system.