Abrova
☰ Docs menu · React Native SDK

React Native SDK

Abrova Auth for React Native and Expo (@abrova/auth-react-native). Anonymous, Apple, Google, e-mail and password, magic link and Telegram sign-in with only your public key; refresh token in the Keychain or Keystore via react-native-keychain or expo-secure-store; token provider for every Abrova SDK.

React Native 0.1.1Expo or bareLast updated: 27 Oct 2026
Client-Safe

Uses the public API key only. Safe to ship in an app

Expo or Bare

react-native-keychain or expo-secure-store for the session

Secure Storage

Refresh token on this device only; access token in memory

Token Provider

tokenProvider and getToken() for the other Abrova SDKs

Same API as Web

One set of calls for your web and mobile code

Upgrade Guests

linkApple, linkGoogle, linkPassword keep the user id

Abrova Auth React Native SDK v0.1.1.

This page describes @abrova/auth-react-native 0.1.1.

Requirements.

React Native with react-native-keychain, or Expo with expo-secure-store. Apple and Google sign-in also need crypto.getRandomValues (react-native-get-random-values).

Using an AI assistant? Give it this page with Copy page for AI, or all the docs as plain text from /docs/llms.txt. See AI assistants.

Installation#

The package comes from Abrova Center. First point the @abrova scope at the Abrova registry in your project's .npmrc:

.npmrcINI
@abrova:registry=https://center.abrova.ir/api/packages/abrova/npm/

Then install it with one of the secure storage libraries:

bash
npm install @abrova/auth-react-native react-native-keychain
# or, with Expo
npx expo install @abrova/auth-react-native expo-secure-store

Or in package.json:

json
{
  "dependencies": {
    "@abrova/auth-react-native": "^0.1.1"
  }
}

For Apple and Google sign-in nonces, also install react-native-get-random-values and import it first thing in index.js:

bash
npm install react-native-get-random-values
typescript
// index.js, before anything else
import 'react-native-get-random-values';

In Abrova Console, turn on Abrova Auth for your project (Settings › Products) and the sign-in methods you want (Abrova Auth › Sign-in methods).

Initialization#

Create one client for your app, with your public API key (ab_live_...) and secure storage:

typescript
import * as Keychain from 'react-native-keychain';
import { createAbrovaAuth, keychainStorage } from '@abrova/auth-react-native';

export const auth = createAbrovaAuth({
  apiKey: 'ab_live_your_api_key',
  storage: keychainStorage(Keychain),
});

auth.onAuthStateChanged((userId) => {
  console.log(userId ? `signed in as ${userId}` : 'signed out');
});

With Expo:

typescript
import * as SecureStore from 'expo-secure-store';
import { createAbrovaAuth, secureStoreStorage } from '@abrova/auth-react-native';

export const auth = createAbrovaAuth({ apiKey: 'ab_live_your_api_key', storage: secureStoreStorage(SecureStore) });

Only the refresh token is stored (Keychain on iOS, Keystore-backed storage on Android, this device only). The access token stays in memory. Without a storage, nothing survives an app restart.

await auth.ready() resolves once the stored session is loaded. onAuthStateChanged calls your listener with the current user id at that point, and again on every sign-in or sign-out.

Sign in#

typescript
const { methods } = await auth.getMethods(); // e.g. ['anonymous', 'apple', 'google']

await auth.ready();
if (!auth.isSignedIn && methods.includes('anonymous')) {
  await auth.signInAnonymously();
}
console.log(auth.currentUserId); // ru_...

Use the user with other Abrova SDKs#

Coming soon. Abrova Sync, Chat, Push, Storage and A/B Testing are coming soon. The calls below show how they will take the Auth user; they are not available yet.
typescript
import AbrovaSync from '@abrova/sync-react-native';

// Sync, Push and A/B Testing: null while signed out
await AbrovaSync.init({ apiKey: 'ab_live_your_api_key', tokenProvider: () => auth.getToken() });

auth.getToken() resolves to a fresh access token, or null when nobody is signed in. auth.tokenProvider rejects with UNAUTHENTICATED instead: use it for Abrova Chat. When the user signs in or out, ask the other SDKs to fetch a new token (for example AbrovaSync.refreshUserToken()). More: Use with other Abrova products.

Sign-in methods#

Each method has its own page with the Console setup: Anonymous, Apple, Google, E-mail & password, Magic link, Telegram.

E-mail and password

typescript
const result = await auth.signUpWithEmail({ email, password, redirectUrl: 'myapp://auth/verify' });
// result.signedIn is false when the project requires a verified e-mail first.

await auth.signInWithEmail({ email, password });

await auth.sendPasswordReset({ email, redirectUrl: 'myapp://auth/reset' });
await auth.resetPassword({ token, password }); // token from the link's ?token=
await auth.verifyEmail({ token });

Magic link

typescript
await auth.sendMagicLink({ email, redirectUrl: 'myapp://auth/magic' });

// When the app is opened with the link (Linking):
const token = new URL(url).searchParams.get('token');
if (token) await auth.signInWithMagicLink({ token });

Telegram

typescript
import { Linking } from 'react-native';

const { sent, botUrl } = await auth.requestTelegramCode({ phone: '+989121234567' });
if (!sent && botUrl) await Linking.openURL(botUrl);
await auth.verifyTelegramCode({ phone: '+989121234567', code: '123456' });

Apple and Google

Run the native sign-in with a nonce from the SDK, then hand its ID token to Abrova:

typescript
const { rawNonce, hashedNonce } = await auth.createNonce();
// Give hashedNonce to your Apple / Google sign-in library as the `nonce`.
await auth.signInWithApple({ idToken, rawNonce, authorizationCode });
await auth.signInWithGoogle({ idToken, rawNonce });

Create a new nonce for every sign-in. Google sign-in needs a connection to Google, and on Android also Google Play services; some users in Iran have neither. Anonymous, e-mail and password, magic link and Telegram code work without Google, so offer at least one of them as well. See Sign in with Google.

Upgrade an anonymous user#

Linking keeps the user id, so the user's data stays theirs:

typescript
import { isAbrovaAuthError } from '@abrova/auth-react-native';

try {
  await auth.linkApple({ idToken, rawNonce }); // or linkGoogle(...), linkPassword({ email, password })
} catch (e) {
  if (isAbrovaAuthError(e) && e.code === 'PROVIDER_ALREADY_LINKED') {
    // This Apple ID already belongs to another user.
  }
}

The current user#

typescript
auth.currentUserId;           // null when signed out
auth.isSignedIn;
const me = await auth.getMe(); // { id, anonymous, emailVerified, createdAt, providers }
auth.currentUser;             // the user last loaded by getMe()

Sign out and delete the account#

typescript
await auth.signOut();           // this device
await auth.signOutEverywhere(); // every device
await auth.deleteAccount();     // deletes the user, then signs out (required by the App Store)

Handle errors#

Every failure is an AbrovaAuthError with a code:

typescript
import { isAbrovaAuthError } from '@abrova/auth-react-native';

try {
  await auth.signInWithEmail({ email, password });
} catch (e) {
  if (isAbrovaAuthError(e) && e.code === 'INVALID_CREDENTIALS') showError('Wrong e-mail or password');
  if (isAbrovaAuthError(e) && e.code === 'RATE_LIMITED') retryIn(e.retryAfterSec);
}

Besides the server's codes the SDK uses NETWORK_ERROR. A network error never signs the user out; a revoked or expired session does (onAuthStateChanged(null)). The access token is renewed 2 minutes before it expires, and calls at the same time share one renewal. All codes: Error codes.

Troubleshooting#

Signed out after every restart

Pass storage: keychainStorage(Keychain) or secureStoreStorage(SecureStore). Without it, the session is kept in memory only.

createNonce fails with NOT_CONFIGURED

crypto.getRandomValues is missing. Install react-native-get-random-values and import it first in index.js.

E-mail link refused with INVALID_INPUT

The redirectUrl must start with one of the link addresses under Abrova Auth › Settings, for example myapp://auth.

Was this page helpful?
Report a problem