Authenticate Users - Kotlin SDK
On this page
Overview
Atlas App Services provides an API for authenticating users using any enabled authentication provider. Instantiate a Credentials object and pass it to app.login() to authenticate and create a User object for that user.
Each authentication provider corresponds to a
static helper method
used to instantiate Credentials
objects for that
authentication provider.
Before You Begin
Enable and configure one or more App Services authentication providers.
Register a New User Account
Realm registers accounts differently depending on the authentication provider:
You do not need to register anonymous users.
To register an email/password user, refer to Manage Email/Password Users.
If you are using Google, Facebook, Apple, or Custom JWT authentication, registration is handled by these third-party services.
Log In
You can authenticate users with app.login().
If successful, app.login()
returns a User
object.
In the event of a failure, app.login()
throws an
exception of type AppException
.
You can get the authentication provider type used to log in a user using the user.provider property. If the user is currently logged out, the provider last used to log in the user will be returned.
Anonymous
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().
val app: App = App.create(YOUR_APP_ID) // Replace this with your App ID runBlocking { // use runBlocking sparingly -- it can delay UI interactions val user = app.login(Credentials.anonymous()) }
If you want more than one anonymous user, set reuseExisting = false
when
creating additional anonymous credentials.
runBlocking { // Logs in with anonymous user val anonUser = app.login(Credentials.anonymous()) // Creates a new anonymous user val otherAnonUser = app.login(Credentials.anonymous(reuseExisting = false)) }
Email/Password
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().
val app: App = App.create(YOUR_APP_ID) // Replace this with your App ID runBlocking { // use runBlocking sparingly -- it can delay UI interactions val user = app.login(Credentials.emailPassword(email, password)) }
Custom JWT
The Custom JWT authentication provider enables users to log in to your application with a custom JSON Web Token. To log in with JWT authentication, create a JWT credential by calling Credentials.jwt() with the user's JWT. Then pass the generated credential to app.login().
val app: App = App.create(YOUR_APP_ID) // Replace this with your App ID runBlocking { // use runBlocking sparingly -- it can delay UI interactions val user = app.login(Credentials.jwt(jwtToken)) }
API Key
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 email/password credential by calling Credentials.apiKey() with the user's email and password. Then pass the generated credential to app.login().
val app: App = App.create(YOUR_APP_ID) // Replace this with your App ID runBlocking { // use runBlocking sparingly -- it can delay UI interactions val user = app.login(Credentials.apiKey(key)) }
Custom Function
If you have configured the Custom Function authentication provider, you can log in using custom authentication logic handled by an Atlas Function.
To log in with Custom Function authentication, pass your custom arguments as a payload to Credentials.customFunction(). Then pass the generated credential to app.login().
val customCredentials = Credentials.customFunction( payload = mapOf("username" to "bob") ) // Pass the generated credential to app.login() val currentUser = app.login(customCredentials)
New in version 1.9.0.
You can serialize data for a custom function credential using an EJSON encoder. For more information, including examples, refer to EJSON Encoding for Atlas.
Google
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. The following
code implements this flow, starting with a method call to
loginWithGoogle()
:
fun loginWithGoogle() { val gso = GoogleSignInOptions .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken("YOUR WEB APPLICATION CLIENT ID FOR GOOGLE AUTH") .build() val googleSignInClient = GoogleSignIn.getClient(activity, gso) val signInIntent: Intent = googleSignInClient.signInIntent val resultLauncher: ActivityResultLauncher<Intent> = // Note: this activity MUST inherit from ComponentActivity or AppCompatActivity to use this API 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 app: App = App.create(YOUR_APP_ID) // Replace this with your App ID runBlocking { val user = app.login(Credentials.google(token, GoogleAuthType.ID_TOKEN)) } } 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.
KMM supports many environments, but this example shows sign-in on the Android platform. For information about signing into a Google account on Apple platforms, see the Swift SDK Example.
Facebook
The Facebook authentication provider allows you to authenticate users through a Facebook app using their existing Facebook account.
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 Facebook credential by calling Credentials.facebook() with the user's access token. Then pass the generated credential to app.login().
val app: App = App.create(YOUR_APP_ID) // Replace this with your App ID 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 runBlocking { val user = app.login(Credentials.facebook(accessToken.token)) } } override fun onCancel() { Log.v("AUTH", "Cancelled Facebook login") } override fun onError(exception: FacebookException) { Log.e("AUTH", "Failed to authenticate with Facebook: ${exception.message}") } })
Tip
See also:
KMM supports many environments, but this example shows sign-in on the Android platform. For information about signing into a Facebook account on Apple platforms, see the Swift SDK Example.
Apple
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 Apple authentication, create an Apple credential by calling Credentials.apple() with the user's token. Then pass the generated credential to app.login().
val app: App = App.create(YOUR_APP_ID) // Replace this with your App ID runBlocking { // use runBlocking sparingly -- it can delay UI interactions val user = app.login(Credentials.apple(idToken)) }
Tip
See also:
KMM supports many environments, but this example shows sign-in on the Android platform. For information about signing in with Apple on Apple platforms, see the Swift SDK Example.
Get a User Access Token
The Realm Kotlin SDK automatically manages access tokens, refreshes them when they expire, and includes a valid access token for the current user with each request. Tokens are removed after the user logs out.
You can get the current access token for a logged-in user with the user.accessToken property:
val token = user.accessToken
If you send requests outside of the SDK (e.g. through the GraphQL API), then you must include the user's access token with each request and manually refresh the token when it expires. Access tokens expire 30 minutes after a user logs in.
You can get the current refresh token for a logged-in user with the user.refreshToken property, which you can use to request a new access token:
// Gets the current refresh token for the user fun getRefreshToken(): String { return user.refreshToken }
Log a User 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.
You can log out any user, regardless of the authentication provider used to log in, using user.logOut().
The user.logOut()
method:
Deletes locally stored user credentials from the device.
Immediately halts 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.logOut()
Retrieve Current User
Once you have an authenticated user, you can retrieve the User object with the
App.currentUser
property.
The currentUser
object is persisted in local storage, so even if
the app shuts down after the initial authentication, you do not need to call
logIn
again (unless the user logged out).
val user = app.currentUser
Authentication Changes as a Flow
New in version 10.8.0.
You can observe a flow of authentication change events by calling App.authenticationChangeAsFlow() . This flow emits AuthenticationChange events of three possible states, represented as subclasses:
LoggedIn
: A user logs into the app.LoggedOut
: A a user logs out of the app.Removed
: A user is removed from the app, which also logs them out.
These events contain a user
property that provides a reference to the
User
object that has logged in, logged out, or been removed.
// Create a Flow of AuthenticationChange objects app.authenticationChangeAsFlow().collect() { change: AuthenticationChange -> when (change) { is LoggedIn -> proceedToAppActivity(change.user) is LoggedOut -> proceedToLoginActivity(change.user) is Removed -> proceedToRemovedUserActivity(change.user) } }