Docs Menu

Docs HomeAtlas Device SDK

Authenticate Users - React Native SDK

On this page

  • Prerequisites
  • Configure User Authentication in Client
  • Set up @realm/react Providers
  • Write a Fallback Component for UserProvider
  • User Sessions
  • Authentication Providers and Client Authentication
  • Anonymous User
  • Email/Password User
  • API Key User
  • Custom JWT User
  • Custom Function User
  • Facebook User
  • Google User
  • Apple User
  • Offline Login
  • Get a User Access Token
  • Refresh Token Expiration
  • Log a User Out
  • useAuth Hook Reference

@realm/react has hooks for user authentication. useAuth and useEmailPasswordAuth handle authentication with enabled authentication providers.

For a quick useAuth reference, refer to useAuth Hook on this page. For a quick useEmailPasswordAuth reference, refer to useEmailPasswordAuth Hook on the Manage Email/Password Users page.

You can also use the Realm.js APIs directly. Instantiate a Credentials object and pass it to App.logIn() to authenticate and obtain a User object.

Before you can authenticate a user, you must:

@realm/react has providers and hooks for user authentication. To configure user authentication:

  1. Set up @realm/react providers.

  2. Write a fallback component for UserProvider.

Components wrapped by AppProvider can access the useApp and useAuth hooks. These components only render if AppProvider successfully connects to your App Services backend.

Components wrapped by UserProvider can access authenticated users with the useUser hook. These components only render if your app has an authenticated user

To configure user authentication:

  1. Wrap all components that need to access App Services in AppProvider.

  2. Inside of AppProvider, wrap all components that you want to have access to an authenticated user with UserProvider.

  3. In UserProvider, include a fallback prop with a component that logs a user in. The app renders this component if there is no authenticated user.

import React from 'react';
import {AppProvider, UserProvider} from '@realm/react';
// Fallback log in component that's defined in another file.
import {LogIn} from './Login';
export const LoginExample = () => {
return (
<ScrollView>
<AppProvider id={APP_ID}>
{/* If there is no authenticated user, mount the
`fallback` component. When user successfully
authenticates, the app unmounts the `fallback`
component (in this case, the `LogIn` component). */}
<UserProvider fallback={LogIn}>
{/* Components inside UserProvider have access
to the user. These components only mount if
there's an authenticated user. */}
<UserInformation />
</UserProvider>
</AppProvider>
</ScrollView>
);
};

If your app doesn't have an authenticated and logged-in user, UserProvider and its children will not render. To handle this case, you can pass a fallback component to UserProvider. This is commonly the login screen for apps.

The following example uses anonymous authentication, but you could use any of the useAuth methods.

To write an authentication fallback component for UserProvider:

  1. Create a functional component.

  2. Destructure logInWithAnonymous and result from the useAuth hook.

  3. Call logInWithAnonymous() within a useEffect block that has an empty dependency array.

  4. Handle result. If the authentication operation doesn't succeed, you can write error handling based on result.

export const LogIn = () => {
// `logInWithAnonymous` logs in a user using an
// anonymous Realm Credential.
// `result` gives us access to the result of the
// current operation. In this case, `logInWithAnonymous`.
const {logInWithAnonymous, result} = useAuth();
// Log in an anyonmous user on component render.
// On successful login, this fallback component unmounts.
useEffect(() => {
logInWithAnonymous();
}, [])
return (
<View >
{!result.error && <Text>Please log in</Text>}
<View>
{result.pending && <ActivityIndicator />}
{result.error && <ErrorComponent error={result.error} />}
</View>
</View>
);
};

The React Native SDK communicates with Atlas App Services to manage sessions with access tokens and refresh tokens.

To learn more about session management, refer to User Sessions in the App Services documentation.

After you configure user authentication in your client and authentication providers in your App Services App, you can log users in.

The Anonymous provider allows users to log in to your application with temporary accounts that have no associated information.

Calling an authentication method when a user is currently logged in, switches the current user to the new user.

If you call logInWithAnonymous() in the fallback of the UserProvider, then UserProvider's children render as soon as the anonymous log in succeeds.

To log in an anonymous user:

  1. Destructure logInWithAnonymous and result from the useAuth hook.

  2. Call logInWithAnonymous() without any arguments.

  3. Handle the result.

export const LogInWithAnonymous = () => {
const {logInWithAnonymous, result} = useAuth();
const performAnonymousLogin = logInWithAnonymous;
// Handle `result`...
};

The email/password authentication provider allows users to log in to your application with an email address and a password.

You can use the useEmailPasswordAuth hook to handle user log in your client. For a quick useEmailPasswordAuth reference, refer to useEmailPasswordAuth Hook on the Manage Email/Password Users page.

To log a user in with email and password:

  1. Destructure logIn and result from the useEmailPasswordAuth hook.

  2. Pass the user's email and password to LogIn() as an object.

  3. Handle the result.

export const LoginWithEmail = () => {
const {logIn, result} = useEmailPasswordAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const performLogin = () => {
logIn({email, password});
};
// Handle `result`...
};

The API key authentication provider allows server processes to access your app directly or on behalf of a user.

To log in with an API key, create an API Key credential with a server or user API key and pass it to App.logIn():

// Get the API key from the local environment
const apiKey = process.env?.appServicesApiKey;
if (!apiKey) {
throw new Error("Could not find a Server API Key.");
}
// Create an api key credential
const credentials = Realm.Credentials.apiKey(apiKey);
const user = await app.logIn(credentials);

The Custom JWT authentication provider handles user authentication with any authentication system that returns a JSON web token.

To log in a custom JWT user:

  1. Set up the JWT authentication provider in your App Services backend.

  2. Get a JWT from an external system.

  3. Destructure logInWithJWT and result from the useAuth hook.

  4. Pass the JWT to logInWithJWT().

  5. Handle the result.

export const LogInWithJWT = () => {
const {logInWithJWT, result} = useAuth();
// Get the current anonymous user so we can call
// an App Services Function later.
const anonymousUser = useUser();
const performJWTLogin = async () => {
// Get a JWT from a provider. In this case, from
// an App Services Function called "generateJWT".
const token = (await anonymousUser.functions.generateJWT()) as string;
logInWithJWT(token);
};
// Handle `result`...
};

The Custom Function authentication provider allows you to handle user authentication by running a function that receives a payload of arbitrary information about a user. Refer to Custom Function Authentication for details.

To log in a user with the custom function provider:

  1. Create an App Services function to handle your authentication needs.

  2. Enable the Custom Function Provider for your App Services App and configure it to use the function you created earlier.

  3. Destructure logInWithFunction and result from the useAuth hook.

  4. Pass any relevant user data (like a username) to logInWithFunction().

  5. Handle the result.

export const LogInWithFunction = () => {
const {logInWithFunction, result} = useAuth();
const performFunctionLogin = async (email: string, password: string) => {
// Pass arbitrary information to the Atlas function configured
// for your App's Custom Function provider.
logInWithFunction({email, password});
};
// Handle `result`...
};

The Facebook authentication provider allows you to authenticate users through a Facebook app using their existing Facebook account.

To log a user in with an existing Facebook account, you must configure and enable the Facebook authentication provider for your App Services App.

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.

You can use the official Facebook SDK to handle the user authentication and redirect flow from a client application. Once authenticated, the Facebook SDK returns an access token that you can send to your React Native app and use to finish logging the user in to your app.

export const LogInWithFacebook = () => {
const {logInWithFacebook, result} = useAuth();
const performLogin = () => {
// Get an access token using the Facebook SDK.
// You must define this function.
const token = getFacebookToken();
logInWithFacebook(token);
};
// Handle `result`...
};

The Google authentication provider allows you to authenticate users with their existing Google account.

To authenticate a Google user, you must configure the Google authentication provider for your App Services App.

There is no official Sign in With Google integration for React Native. The simplest approach to integrating Sign in With Google into your React Native app with Realm authentication is to use a third-party library. You can also build your own solution using Google Identity Services to handle the user authentication and redirect flow from a client application.

Regardless of implementation, you must retrieve an ID token from the Google Authorization server. Use that ID token to log into Realm.

export const LogInWithGoogle = () => {
const {logInWithGoogle, result} = useAuth();
const performLogin = () => {
// Get an access token using a third-party library
// or build your own solution. You must define this function.
const token = getGoogleToken();
logInWithGoogle(token);
};
// Handle `result`...
};

The Apple authentication provider allows you to authenticate users through Sign-in With Apple.

To authenticate an Apple user, you must configure the Apple authentication provider for your App Services App.

You can use the official Sign in with Apple JS SDK to handle the user authentication and redirect flow from a client application. Once authenticated, the Apple JS SDK returns an ID token that you can send to your React Native app and use to finish logging the user in to your app.

export const LogInWithApple = () => {
const {logInWithApple, result} = useAuth();
const performLogin = () => {
// Get an access token using the Apple SDK.
// You must define this function.
const token = getAppleToken();
logInWithApple(token);
};
// Handle `result`...
};

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.

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 user into your App Services App.
// On first login, the user must have a network connection.
const getUser = async () => {
// If the device has no cached user credentials, log in.
if (!app.currentUser) {
const credentials = Realm.Credentials.anonymous();
await app.logIn(credentials);
}
// If the app is offline, but credentials are
// cached, return existing user.
return app.currentUser!;
};

To learn how to use the cached user in the Sync Configuration and access a realm while offline, read the Open a Synced Realm While Offline docs.

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 (for example, through the GraphQL API) then 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:

const RefreshUserAcessToken = () => {
const user = useUser();
const [accessToken, setAccessToken] = useState<string | null>();
// Gets a valid user access token to authenticate requests
const refreshAccessToken = async () => {
// An already logged in user's access token might be stale. To
// guarantee that the token is valid, refresh it if necessary.
await user.refreshCustomData();
setAccessToken(user.accessToken);
};
// Use access token...
};

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.

To log any user out, call the User.logOut() method on their user instance.

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.

function UserInformation() {
const user = useUser();
const {logOut} = useAuth();
const performLogout = () => {
logOut();
};
// Add UI for logging out...
}

The useAuth hook has an authentication method for every App Services authentication provider. It also has state related to authentication. Refer to the useAuth reference for details.

You can also check out the @realm/react API documentation for useAuth.

←  Create and Delete Users - React Native SDKCustom User Data - React Native SDK →