Abrova
☰ Docs menu · Use with other Abrova products

Use with Other Abrova Products

The signed-in Abrova Auth user's token is the standard Abrova user token. Pass the Auth SDK's token provider to Abrova Sync, Chat, Push, A/B Testing and Storage, and their security rules see the user as auth.uid. No backend needed.

Last updated: 27 Oct 2026
One user for every Abrova product.

Abrova Sync, Chat, Push, A/B Testing and Storage identify your app's user with a signed Abrova user token. Without Abrova Auth, your own server mints that token with the server secret. With Abrova Auth, the Auth SDK has the token already: hand its token provider to the other SDKs and they act as the signed-in user.

Coming soon. Abrova Sync, Chat, Push, Storage and A/B Testing are coming soon. This page shows how they will take the Auth user once they launch; they cannot be used yet. Today the signed-in user works with Abrova Trace.

Abrova Trace, today#

Abrova Trace is live. Give it the Abrova Auth user id, so errors and crashes show which user they happened to. Set it after sign-in and clear it after sign-out:

dart
// Flutter
AbrovaTrace.setUserId(AbrovaAuth.instance.currentUser!.id);
swift
// iOS
AbrovaTrace.shared.setUserId(AbrovaAuth.shared.currentUserId)   // nil after sign-out
kotlin
// Android
AbrovaTrace.setUserId(AbrovaAuth.shared.currentUserId)   // null after sign-out

Trace takes the user id only; it does not need the token. See the Trace Flutter SDK, iOS SDK and Android SDK.

What you get#

  • Sync security rules work without a server. auth.uid is the Abrova Auth user id (ru_...), so data.ownerId === auth.uid protects each user's documents. See Sync security rules.
  • Chat knows who is talking. Messages are sent as the token's user; nobody can write as someone else.
  • Storage access rules see the user. Rules like users/{userId}/** let each user read and write only their own files. See Storage access rules.
  • A/B Testing and Push attach events, variants and inbox messages to the user, including anonymous users who have not signed in properly yet.
  • Nothing extra to wire. The other SDKs take a token provider. The token is the same one your own server would mint.

How the token flows#

  1. 1Another Abrova SDK needs a tokenAt start, before a request, or when its token is about to expire, it calls the provider you gave it.
  2. 2The Auth SDK answersWith the current access token, renewed first if it has less than 2 minutes left. Calls at the same moment share one renewal.
  3. 3The product checks itIt verifies the signature, the project and the expiry, and takes the user id from the token.

When nobody is signed in, the provider returns no token (or, for Chat, throws), and each SDK waits for a user the way its docs describe.

Pass the token provider#

These products are coming soon; the calls below are how they will take the token.

Use the user's id from Abrova Auth wherever an SDK asks for a user id (Chat's userId, A/B Testing's setUserId), so it matches the token.

Flutter

dart
final auth = AbrovaAuth.instance;

// Abrova Sync
await AbrovaSync.init(AbrovaSyncConfig(
  apiKey: 'ab_live_your_api_key',
  tokenProvider: auth.tokenProvider,
));

// Abrova Push
await AbrovaPush.init(AbrovaPushConfig(
  apiKey: 'ab_live_your_api_key',
  tokenProvider: auth.tokenProvider,
));

// Abrova A/B Testing
await AbrovaAbTesting.init(AbrovaAbTestingConfig(
  apiKey: 'ab_live_your_api_key',
  tokenProvider: auth.tokenProvider,
));

// Abrova Storage
final storage = AbrovaStorage(
  apiKey: 'ab_live_your_api_key',
  tokenProvider: auth.tokenProvider,
);

// Abrova Chat: its provider must return a token, so use chatTokenProvider
final chat = AbrovaChatClient(AbrovaChatConfig(
  apiKey: 'ab_live_your_api_key',
  userId: auth.currentUser!.id,
  tokenProvider: auth.chatTokenProvider,
));

tokenProvider returns null when nobody is signed in. chatTokenProvider throws UNAUTHENTICATED instead; create the Chat client after sign-in.

iOS

swift
let auth = AbrovaAuth.shared

// Abrova Sync
sync.userTokens.provider = auth.tokenProvider

// Abrova Push
AbrovaPushConfig(apiKey: key, tokenProvider: auth.tokenProvider)

// Abrova Storage
let storage = AbrovaStorage(apiKey: key, userTokenProvider: auth.tokenProvider)

// Abrova Chat: create the client after sign-in
AbrovaChatConfig(apiKey: key, userId: auth.currentUserId!, tokenProvider: auth.strictTokenProvider)

// Abrova A/B Testing takes a completion handler
AbrovaAbTestingConfig(apiKey: key, tokenProvider: { completion in
    Task {
        do { completion(.success(try await auth.strictTokenProvider())) }
        catch { completion(.failure(error)) }
    }
})

tokenProvider returns nil when nobody is signed in; strictTokenProvider throws.

Android

kotlin
val auth = AbrovaAuth.shared

// Abrova Sync: its provider is called off the main thread
AbrovaSyncConfig.builder(apiKey).userTokenProvider(auth.blockingTokenProvider).build()

// Abrova Push
AbrovaPushConfig(apiKey = apiKey, tokenProvider = auth.tokenProvider)

// Abrova Storage: also called off the main thread
AbrovaStorage.builder(apiKey).userTokenProvider(auth.blockingTokenProvider).build()

// Abrova A/B Testing: also called off the main thread
AbrovaAbTestingConfig(apiKey = apiKey, tokenProvider = AbrovaTokenProvider { auth.blockingTokenProvider() })

// Abrova Chat: create the client after sign-in
AbrovaChatConfig(apiKey = apiKey, userId = auth.currentUserId!!, tokenProvider = auth.strictTokenProvider)

tokenProvider is a suspend function that returns null when nobody is signed in; strictTokenProvider throws instead; blockingTokenProvider blocks the calling thread and must never run on the main thread.

Web

typescript
import { createAbrovaAuth } from '@abrova/auth-web';
import { AbrovaSync } from '@abrova/sync-web';
import { AbrovaStorage } from '@abrova/storage-web';

const auth = createAbrovaAuth({ apiKey: 'ab_live_your_api_key' });

// Abrova Sync, Push, A/B Testing and Storage: null while signed out
const sync = new AbrovaSync({ apiKey: 'ab_live_your_api_key', tokenProvider: () => auth.getToken() });
const storage = new AbrovaStorage({ apiKey: 'ab_live_your_api_key', tokenProvider: () => auth.getToken() });

// Abrova Chat: auth.tokenProvider rejects with UNAUTHENTICATED while signed out
const chat = new AbrovaChatClient({
  apiKey: 'ab_live_your_api_key',
  userId: auth.currentUserId!,
  tokenProvider: auth.tokenProvider,
});

React Native

typescript
import AbrovaSync from '@abrova/sync-react-native';
import { AbrovaStorage } from '@abrova/storage-react-native';

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

// Abrova Chat: create the client after sign-in
const chat = new AbrovaChatClient({
  apiKey: 'ab_live_your_api_key',
  userId: auth.currentUserId!,
  tokenProvider: auth.tokenProvider,
});

When the user signs in or out#

The other SDKs cache the token they have. After a sign-in, a sign-out or a switch to another user, tell them to ask the provider again:

ProductCall
Abrova SyncAbrovaSync.refreshUserToken() (Flutter, React Native, Web); sync.userTokens.refresh() (Android); sync.refreshUserToken() (iOS)
Abrova A/B TestingrefreshUserToken() after sign-in; clearUserId() after sign-out
Abrova Storagestorage.refreshUserToken() (every platform). While nobody is signed in, file calls wait and go on after sign-in.
Abrova ChatCreate the client for the new user; disconnect the old one

Listen to the Auth SDK's auth state (authStateChanges, onAuthStateChanged, addAuthStateListener or authState) and make these calls there, so every product follows the user.

Write security rules for the user#

The user id in the token is auth.uid in Abrova Sync rules. Store it in the documents a user owns:

json
{
  "rules": {
    "notes": {
      ".read": "data.ownerId === auth.uid",
      ".write": "newData.ownerId === auth.uid"
    }
  }
}
dart
await AbrovaSync.database('my-app').collection('notes').add({
  'ownerId': AbrovaAuth.instance.currentUser!.id,
  'text': 'Hello',
});

Then turn on Require signed user tokens for Sync in the Console, so only a signed token can set auth.uid. See Sync security rules.

With your own server too#

You can still mint tokens on your own server with the server secret (POST https://auth.abrova.ir/users/token) for your own user ids. Both kinds of token work in every product. Keep one source of user ids per app, so the same person is not two users.

Was this page helpful?
Report a problem