Authenticate Users - Java SDK
On this page
Realm provides an API for authenticating users using any enabled
authentication provider. Instantiate a Credentials
object and pass
it to either of the app.login()
or app.loginAsync()
methods to
authenticate a user login and create a User
object. Each
authentication provider corresponds to a static helper method used to
instantiate Credentials
objects using that authentication provider.
Log In
You can authenticate users with either the app.login()
or
app.loginAsync()
methods of your application's instance of the
io.realm.mongodb.App
class. While the app.login()
method blocks
code execution in the calling thread until the supplied credentials have
either succeeded or failed to authenticate a user, the
app.loginAsync()
method allows execution to continue, handling
success or failure with a callback function that is guaranteed to
execute on the same thread that called app.loginAsync()
.
If successful, the app.login()
method returns a User
object.
In the event of a failure, the app.login()
method throws an
exception of type ObjectServerError
.
Pass a callback to the app.loginAsync()
method to handle success or
failure. This callback accepts a single parameter of type
App.Result
. The isSuccess()
method of the App.Result
object
passed to the callback returns a boolean that indicates whether the
operation succeeded. In the event of a failure, you can view the
error that caused the failure using the getError()
method.
Anonymous User
The anonymous authentication provider
enables users to log in to your application with short-term accounts
that store no persistent personal information. To log in with anonymous
authentication, create an anonymous credential by calling
Credentials.anonymous()
and then pass the generated credential to
app.login()
or app.loginAsync()
.
String appID = YOUR_APP_ID; // replace this with your App ID App app = new App(new AppConfiguration.Builder(appID) .build()); Credentials anonymousCredentials = Credentials.anonymous(); AtomicReference<User> user = new AtomicReference<User>(); app.loginAsync(anonymousCredentials, it -> { if (it.isSuccess()) { Log.v("AUTH", "Successfully authenticated anonymously."); user.set(app.currentUser()); } else { Log.e("AUTH", it.getError().toString()); } });
val appID = YOUR_APP_ID // replace this with your App ID val app: App = App( AppConfiguration.Builder(appID) .build() ) val anonymousCredentials: Credentials = Credentials.anonymous() var user: User? app.loginAsync(anonymousCredentials) { if (it.isSuccess) { Log.v("AUTH", "Successfully authenticated anonymously.") user = app.currentUser() } else { Log.e("AUTH", it.error.toString()) } }
Email/Password User
The Email/Password authentication provider
enables users to log in to your application with an email username and
a password. To log in with email/password authentication, create an
email/password credential by calling Credentials.emailPassword()
with the user's email and password. Then pass the generated credential
to app.login()
or app.loginAsync()
.
String appID = YOUR_APP_ID; // replace this with your App ID App app = new App(new AppConfiguration.Builder(appID) .build()); Credentials emailPasswordCredentials = Credentials.emailPassword("<email>", "<password>"); AtomicReference<User> user = new AtomicReference<User>(); app.loginAsync(emailPasswordCredentials, it -> { if (it.isSuccess()) { Log.v("AUTH", "Successfully authenticated using an email and password."); user.set(app.currentUser()); } else { Log.e("AUTH", it.getError().toString()); } });
val appID = YOUR_APP_ID // replace this with your App ID val app: App = App( AppConfiguration.Builder(appID) .build() ) val emailPasswordCredentials: Credentials = Credentials.emailPassword( "<email>", "<password>" ) var user: User? = null app.loginAsync(emailPasswordCredentials) { if (it.isSuccess) { Log.v("AUTH", "Successfully authenticated using an email and password.") user = app.currentUser() } else { Log.e("AUTH", it.error.toString()) } }
API Key User
The API Key authentication provider
enables users to log in to your application with an API Key generated
automatically in the client SDK. To log in with API Key authentication, create an
API Key credential by calling Credentials.apiKey()
with an API Key. Then pass the generated credential
to app.login()
or app.loginAsync()
.
String appID = YOUR_APP_ID; // replace this with your App ID App app = new App(new AppConfiguration.Builder(appID) .build()); Credentials apiKeyCredentials = Credentials.apiKey("<key>"); AtomicReference<User> user = new AtomicReference<User>(); app.loginAsync(apiKeyCredentials, it -> { if (it.isSuccess()) { Log.v("AUTH", "Successfully authenticated using an API Key."); user.set(app.currentUser()); } else { Log.e("AUTH", it.getError().toString()); } });
val appID = YOUR_APP_ID // replace this with your App ID val app: App = App( AppConfiguration.Builder(appID) .build() ) val apiKeyCredentials: Credentials = Credentials.apiKey("<key>") var user: User? = null app.loginAsync(apiKeyCredentials) { if (it.isSuccess) { Log.v("AUTH", "Successfully authenticated using an API Key.") user = app.currentUser() } else { Log.e("AUTH", "Error logging in: ${it.error.toString()}") } }
Custom JWT User
The Custom JWT authentication provider
enables users to log in to your application with a custom JSON Web Token.
To log in with custom JWT authentication, create a
custom JWT credential by calling Credentials.jwt()
with your custom JWT. Then pass the generated credential
to app.login()
or app.loginAsync()
.
String appID = YOUR_APP_ID; // replace this with your App ID App app = new App(new AppConfiguration.Builder(appID) .build()); // fetch JWT from custom provider Credentials customJWTCredentials = Credentials.jwt("<token>"); AtomicReference<User> user = new AtomicReference<User>(); app.loginAsync(customJWTCredentials, it -> { if (it.isSuccess()) { Log.v("AUTH", "Successfully authenticated using a custom JWT."); user.set(app.currentUser()); } else { Log.e("AUTH", it.getError().toString()); } });
val appID = YOUR_APP_ID // replace this with your App ID val app: App = App( AppConfiguration.Builder(appID) .build() ) // fetch JWT from custom provider val customJWTCredentials: Credentials = Credentials.jwt("<token>") var user: User? = null app.loginAsync(customJWTCredentials) { if (it.isSuccess) { Log.v("AUTH", "Successfully authenticated using a custom JWT.") user = app.currentUser() } else { Log.e("AUTH", "Error logging in: ${it.error.toString()}") } }
Custom Function User
The Custom Function authentication provider
enables users to log in to your application using a
Realm Function defined in your App. To log in with custom
function authentication, create a credential by calling
Credentials.customFunction()
. The customFunction() method expects a
Document that contains the properties and values used by the Realm auth function.
For example, suppose the backend function expects the input parameter to include
a field named username
, like this:
exports = async function(loginPayload) { const { username } = loginPayload; ... }
The document you pass to Credentials.customFunction()
might look like this:
Document("username", "bob")
You then pass the generated credential to app.login()
or app.loginAsync()
.
String appID = YOUR_APP_ID; // replace this with your App ID App app = new App(new AppConfiguration.Builder(appID).build()); Credentials customFunctionCredentials = Credentials.customFunction(new org.bson.Document("username", "bob")); AtomicReference<User> user = new AtomicReference<User>(); app.loginAsync(customFunctionCredentials, it -> { if (it.isSuccess()) { Log.v("AUTH", "Successfully authenticated using a custom function."); user.set(app.currentUser()); } else { Log.e("AUTH", it.getError().toString()); } });
val appID = YOUR_APP_ID // replace this with your App ID val app: App = App( AppConfiguration.Builder(appID) .build() ) val customFunctionCredentials: Credentials = Credentials.customFunction(org.bson.Document("username", "bob")) var user: User? = null app.loginAsync(customFunctionCredentials) { if (it.isSuccess) { Log.v("AUTH", "Successfully authenticated using a custom function.") user = app.currentUser() } else { Log.e("AUTH", "Error logging in: ${it.error.toString()}") } }
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 Android Quickstart to set up the authentication flow for your application. In the login completion handler, get the logged in user's access token from the Facebook LoginResult. Use the access token to create a Realm Facebook credential and then log the user into your Realm app.
FacebookSdk.setApplicationId(YOUR_FACEBOOK_SDK_APP_ID); FacebookSdk.sdkInitialize(activity); CallbackManager callbackManager = CallbackManager.Factory.create(); LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback<LoginResult>() { public void onSuccess(LoginResult loginResult) { // Signed in successfully, forward credentials to MongoDB Realm. AccessToken accessToken = loginResult.getAccessToken(); Credentials facebookCredentials = Credentials.facebook(accessToken.getToken()); app.loginAsync(facebookCredentials, it -> { if (it.isSuccess()) { Log.v("AUTH", "Successfully logged in to MongoDB Realm using Facebook OAuth."); } else { Log.e("AUTH", "Failed to log in to MongoDB Realm", it.getError()); } }); } public void onCancel() { Log.v("AUTH", "Facebook authentication cancelled."); } public void onError(FacebookException exception) { Log.e("AUTH", "Failed to authenticate using Facebook: " + exception.getMessage()); } } ); LoginManager.getInstance().logIn(activity, null);
FacebookSdk.setApplicationId(YOUR_FACEBOOK_SDK_APP_ID) FacebookSdk.sdkInitialize(activity) val callbackManager = CallbackManager.Factory.create() LoginManager.getInstance().registerCallback( callbackManager, object : FacebookCallback<LoginResult> { override fun onSuccess(loginResult: LoginResult) { // Signed in successfully, forward credentials to MongoDB Realm. val accessToken = loginResult.accessToken val facebookCredentials: Credentials = Credentials.facebook(accessToken.token) app.loginAsync(facebookCredentials) { if (it.isSuccess) { Log.v( "AUTH", "Successfully logged in to MongoDB Realm using Facebook OAuth." ) } else { Log.e("AUTH", "Failed to log in to MongoDB Realm", it.error) } } } override fun onCancel() { Log.v("AUTH", "Cancelled Facebook login") } override fun onError(exception: FacebookException) { Log.e("AUTH", "Failed to authenticate with Facebook: ${exception.message}") } })
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.
To set up your application for Google User authentication:
In the Google Cloud Platform console, create an OAuth 2.0 client ID of type "Web application".
Configure your backend App to use that client ID and the associated client secret.
Enable OpenID Connect on the backend.
Use Google's official Sign-In for Android to authenticate Google users in your Android application:
Note
Code Example Below
For an implementation of these instructions, check out the code block below.
Add the Google Sign-In for Android dependency to the
dependencies
block of your application levelbuild.gradle
:com.google.android.gms:play-services-auth:19.2.0 Create a GoogleSignInOptions with the following builder options:
an ID token request -- pass your OAuth 2.0 client ID as the
serverClientId
.
Use the
GoogleSignInOptions
to create aGoogleSignInClient
with GoogleSignIn.getClient()Use the
GoogleSignInClient
to create anIntent
capable of triggering Google Sign-In.Use registerForActivityResult() to configure a callback. Your callback should use GoogleSignIn.getSignedInAccountFromIntent() to access the result of Google Sign-In: a
Task<GoogleSignInAccount>
.Use the launch() method of the ActivityResultLauncher returned in the previous step to start Google Sign-In. Pass the
launch()
method your Google Sign-InIntent
.Use
isSuccessful()
to handle Google Sign-In errors.Access the result of the task (a GoogleSignInAccount) with
getResult()
.Access the ID token for the
GoogleSignInAccount
withgetIdToken()
.Create a Realm
Credentials
object with Credentials.google(). Pass the ID token as the first parameter, and GoogleAuthType.ID_TOKEN as the second parameter.Use the app.loginAsync() or app.login() methods to authenticate with the Atlas App Services backend using the token.
The following code implements this flow, starting with a method call to
loginWithGoogle()
:
private void signInWithGoogle() { GoogleSignInOptions gso = new GoogleSignInOptions .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken("YOUR WEB APPLICATION CLIENT ID FOR GOOGLE AUTH") .build(); GoogleSignInClient googleSignInClient = GoogleSignIn.getClient(this, gso); Intent signInIntent = googleSignInClient.getSignInIntent(); ActivityResultLauncher<Intent> resultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { public void onActivityResult(ActivityResult result) { Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(result.getData()); handleSignInResult(task); } }); resultLauncher.launch(signInIntent); } private void handleSignInResult(Task<GoogleSignInAccount> completedTask) { try { if (completedTask.isSuccessful()) { GoogleSignInAccount account = completedTask.getResult(ApiException.class); String token = account.getIdToken(); Credentials googleCredentials = Credentials.google(token, GoogleAuthType.ID_TOKEN); app.loginAsync(googleCredentials, it -> { if (it.isSuccess()) { Log.v("AUTH", "Successfully logged in to MongoDB Realm using Google OAuth."); } else { Log.e("AUTH", "Failed to log in to MongoDB Realm: ", it.getError()); } }); } else { Log.e("AUTH", "Google Auth failed: " + completedTask.getException().toString()); } } catch (ApiException e) { Log.w("AUTH", "Failed to log in with Google OAuth: " + e.getMessage()); } }
fun loginWithGoogle() { val gso = GoogleSignInOptions .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken("YOUR WEB APPLICATION CLIENT ID FOR GOOGLE AUTH") .build() val googleSignInClient = GoogleSignIn.getClient(this, gso) val signInIntent: Intent = googleSignInClient.signInIntent val resultLauncher: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> val task: Task<GoogleSignInAccount> = GoogleSignIn.getSignedInAccountFromIntent(result.data) handleSignInResult(task) } resultLauncher.launch(signInIntent) } fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) { try { if (completedTask.isSuccessful) { val account: GoogleSignInAccount? = completedTask.getResult(ApiException::class.java) val token: String = account?.idToken!! val googleCredentials: Credentials = Credentials.google(token, GoogleAuthType.ID_TOKEN) app.loginAsync(googleCredentials) { if (it.isSuccess) { Log.v( "AUTH", "Successfully logged in to MongoDB Realm using Google OAuth." ) } else { Log.e("AUTH", "Failed to log in to MongoDB Realm", it.error) } } } else { Log.e("AUTH", "Google Auth failed: ${completedTask.exception}") } } catch (e: ApiException) { Log.e("AUTH", "Failed to authenticate using Google OAuth: " + e.message); } }
Tip
See also:
To learn more about Google Sign-In for Android, check out the official Google Sign-In for Android Integration Guide.
Apple User
The Sign-in with Apple authentication provider
enables users to log in to your application with a custom token provided
by Apple. To log in with Sign-in with Apple authentication, create a
Sign-in with Apple credential by calling Credentials.apple()
with the token provided by Apple. Then pass the generated credential
to app.login()
or app.loginAsync()
.
String appID = YOUR_APP_ID; // replace this with your App ID App app = new App(new AppConfiguration.Builder(appID) .build()); // fetch apple token using Apple SDK Credentials appleCredentials = Credentials.apple("<token>"); AtomicReference<User> user = new AtomicReference<User>(); app.loginAsync(appleCredentials, it -> { if (it.isSuccess()) { Log.v("AUTH", "Successfully authenticated using Sign-in with Apple."); user.set(app.currentUser()); } else { Log.e("AUTH", it.getError().toString()); } });
val appID = YOUR_APP_ID // replace this with your App ID val app: App = App( AppConfiguration.Builder(appID) .build() ) // fetch IDToken using Apple SDK val appleCredentials: Credentials = Credentials.apple("<token>") var user: User? = null app.loginAsync(appleCredentials) { if (it.isSuccess) { Log.v("AUTH", "Successfully authenticated using Sign-in with Apple.") user = app.currentUser() } else { Log.e("AUTH", "Error logging in: ${it.error.toString()}") } }
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.
Offline Login
App Services manages sessions with access tokens and refresh tokens. Client SDKs supply the logic to manage tokens, and provide them with requests.
The SDK stores these tokens in Shared Preferences.
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. String appID = YOUR_APP_ID; // replace this with your App ID App app = new App(new AppConfiguration.Builder(appID) .build()); // Check for an existing user. // If the user is offline but credentials are // cached, this returns the existing user. AtomicReference<User> user = new AtomicReference<User>(); user.set(app.currentUser()); if (user.get() == null) { // If the device has no cached user // credentials, log them in. Credentials anonymousCredentials = Credentials.anonymous(); app.loginAsync(anonymousCredentials, it -> { if (it.isSuccess()) { Log.v("AUTH", "Successfully authenticated anonymously."); user.set(app.currentUser()); } else { Log.e("AUTH", it.getError().toString()); } }); }
// Log the user into the backend app. // The first time you login, the user must have a network connection. val appID = YOUR_APP_ID // replace this with your App ID val app = App( AppConfiguration.Builder(appID) .build() ) // Check for an existing user. // If the user is offline but credentials are // cached, this returns the existing user. val user = AtomicReference<User?>() user.set(app.currentUser()) if (user.get() == null) { // If the device has no cached user // credentials, log them in. val anonymousCredentials = Credentials.anonymous() app.loginAsync( anonymousCredentials ) { it: App.Result<User?> -> if (it.isSuccess) { Log.v("AUTH", "Successfully authenticated anonymously.") user.set(app.currentUser()) } else { Log.e("AUTH", it.error.toString()) } } }
Get a User Access Token
When a user logs in, Atlas App Services creates an access token for the user that grants them access to your App. 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. Realm does not automatically refresh the refresh token. When the refresh token expires, the user must log in again.
If you send requests outside of the SDK, you need to include the user's access token with each request and manually refresh the token when it expires.
You can access and refresh a logged in user's access token in the SDK from their
Realm.User
object, as in the following example:
// Gets a valid user access token to authenticate requests public String getValidAccessToken(User user) { // An already logged in user's access token might be stale. To // guarantee that the token is valid, refresh it if necessary. user.refreshCustomData(); return user.getAccessToken(); }
// Gets a valid user access token to authenticate requests fun getValidAccessToken(user: User?): String { // An already logged in user's access token might be stale. To // guarantee that the token is valid, refresh it if necessary. user!!.refreshCustomData() return user.accessToken }
Log a User Out
You can log out any user, regardless of the authentication provider used
to log in, using the user.logOut()
or user.logOutAsync()
methods. Both methods:
delete locally stored user credentials from the device
immediately halt any synchronization to and from the user's realms
Because logging out halts synchronization, you should only log out after all local Realm updates have uploaded to the server.
user.get().logOutAsync( result -> { if (result.isSuccess()) { Log.v("AUTH", "Successfully logged out."); } else { Log.e("AUTH", result.getError().toString()); } });
user?.logOutAsync { if (it.isSuccess) { Log.v("AUTH", "Successfully logged out.") } else { Log.e("AUTH", it.error.toString()) } }