Limit User Credentials to One Device at a Time

Context

We have a Mac app that relies on Realm and Device Sync. Users are authenticated via email/password. The app’s customers are enterprises that pay for a certain number of user accounts (one account for each employee, etc.)

To combat credential-sharing, we’d like to impose a condition such that when a user logs in on one Mac, any active sessions on other devices are automatically logged out. This way, a customer can’t purchase 3 user accounts and share them across 17 employees, for instance. (This app is designed such that online access is required—the app will gracefully shutdown if disconnected from Device Sync.)

I know the Atlas APIs have a “custom user authentication” flow and that I can list all users and all devices for a user. But before I dive into implementing all that, is there a simple way in the Realm Swift SDK to say: “Log this user in, and terminate any other sessions he might already have running”?

Hi @Bryan_Jones,

The Realm SDKs don’t have this functionality built in, but you can accomplish something similar using the App Services Admin API /logout endpoint which will revoke all sessions for the given user ID. You would likely want to call this before login since it will otherwise revoke the session that was just logged in.

1 Like

Thanks! I did see that endpoint, but it takes the ID of a user. Is there a simple way to look up that ID by email address?

At the app’s log-in screen, I’ll have the user’s email and password. To revoke their other sessions I need the associated userID. There are only two ways I see to get that:

  1. Log the user in, then inspect the user metadata to get the id. Revoke all sessions using the ID, then log in AGAIN. (Not great.)

  2. Use the endpoint to dump ALL users and then enumerate them until I find the one with a given email. (Also not great—potentially many users, paginated responses, etc.)

Is there a cleaner way?

Unfortunately there’s no way currently to programmatically look up a user from their auth provider metadata. Your best bet for now would be to do the first option (which I recognize is not great), or alternatively you could use custom user data that lives in your cluster to lookup the user ID for a given email address.

You can also feel free to upvote this feature request which may help with your use case.

Just spit balling… what if you have a collection dedicated to storing user data including fields like the user id, email address, etc at the point of registration. Inserts to the collection could be done via an auth create trigger whenever a new user registers.

When a login happens, you could call a function from the SDK sending the email address as a function argument before the login happens in the sdk. The function can do a query to look up the email address in the user collection and find the id before using the logout API within the function itself.

I considered that, but the docs for calling functions seem to require that a user first be logged into the Realm:

That’s true, perhaps then a call to a https endpoint that runs the function?
It still requires user auth but this can be a server API key