Expo SDK
Expo SDK quickstart for @layers/amba-expo — config plugin, Apple/Google sign-in, push integration, and prebuild workflow. Builds on @layers/amba-react-native.
@layers/amba-expo is the Expo wrapper around @layers/amba-react-native. It re-exports the same Amba singleton, and adds an Expo config plugin that wires up the native config the SDK needs (push entitlements, URL schemes, Associated Domains, Android intent filters) at prebuild time.
Use this SDK if you're on the Expo managed workflow or building with EAS Build. For bare React Native apps without Expo modules, use @layers/amba-react-native directly.
1. Install
Expo will pick the version of each peer that matches your SDK version.
Token storage
On iOS and Android builds, Amba.configure() stores the session and refresh tokens in SecureStore (Keychain on iOS, EncryptedSharedPreferences on Android) when expo-secure-store and AsyncStorage are both installed and SecureStore is available on the device. Install expo-secure-store in every app that signs users in.
Where SecureStore is missing or unavailable (web, for example), the tokenStorage option of Amba.configure() decides, and the SDK logs one warning:
tokenStorage | Tokens live in | After a restart |
|---|---|---|
"secure" (default) | SecureStore, else memory | Signed in with SecureStore, else signed out |
"memory" | Memory only | Signed out |
"asyncStorage" | Plain AsyncStorage (readable from the app's files and unencrypted backups) | Signed in |
Choose "asyncStorage" only when the platform has no keystore and signing in again on every launch is unacceptable.
Where SecureStore holds the tokens, it also holds the anonymous id (from @layers/amba-expo 4.0.13), which signs a purely anonymous user back in. The first launch after an upgrade moves the anonymous id there from AsyncStorage. The user id stays in AsyncStorage. Without SecureStore, the anonymous id and user id stay in AsyncStorage.
Crypto setup
Required. Hermes (Expo's default JS engine) does not ship crypto.getRandomValues. Amba uses it to generate identifiers that need to be unpredictable, such as the anonymous id that signs an anonymous user back in. Without the polyfill, Amba.configure() throws SecureRandomUnavailableError (from @layers/amba-expo 4.0.13).
Import react-native-get-random-values once, as the very first import in your app's entry file, before any other Amba imports:
Order matters: the polyfill installs crypto.getRandomValues on the global object as a side effect of being imported. If Amba loads first, it captures the (missing) global and the polyfill never takes effect. Put the import on line 1.
A one-shot console warning fires at runtime if Amba sees the fallback path engaged — that's your signal the polyfill import is missing or out of order. See the React Native SDK crypto setup section for the full rationale.
2. Add the config plugin to app.json
The plugin accepts these options:
scheme— adds aCFBundleURLTypesentry on iOS somyapp://...deep-links route into the app, and anintent-filteron the Android main activity for the same scheme.googleIosClientId— appends a reverse-DNS-edCFBundleURLTypesentry so the Google sign-in redirect lands back in the app.projectIdandclientKey— accepted in the plugin options for symmetry withAmba.configure(...); runtime config is the canonical source.
For Universal Links / APS Environment / UIBackgroundModes / Google Web client wiring, configure them directly in app.json's ios.associatedDomains / ios.entitlements / android.permissions and the corresponding native config blocks.
Re-run npx expo prebuild --clean after changing plugin properties.
3. Configure the SDK at runtime
The plugin only handles native config — runtime initialization still happens via Amba.configure({ projectId, clientKey }). Keep EXPO_PUBLIC_AMBA_PROJECT_ID and EXPO_PUBLIC_AMBA_CLIENT_KEY in your env so the same values reach both prebuild and runtime.
For EAS Build, set the same env in your eas.json:
4. Sign in with Apple
The plugin wires the entitlement; the runtime call uses expo-apple-authentication:
await Amba.signInWithApple() runs the same sheet and also binds the attempt to a one-time sign-in nonce, so an identity token issued to another sign-in (a different app sharing your client id, or a different attempt) can't be exchanged without that attempt's raw nonce. It needs expo-crypto or react-native-get-random-values for the nonce. When you call signInAsync yourself, pass a nonce the same way: the SHA-256 hash to Apple, the raw value to Amba.auth.signInWithApple(token, { nonce }).
5. Sign in with Google
The plugin's googleIosClientId property keeps the iOS Google sign-in client id consistent between prebuild and runtime — set it once in app.json and reference it at runtime via env vars. (For Android, the OAuth client id comes from the Google Play Console; you don't need a plugin field.)
6. Push integration
Call this after a successful sign-in or after the user explicitly opts in.
APNs entitlement wiring isn't in the plugin today (see § 2). Until it lands, add the APS Environment entitlement and
UIBackgroundModes: ["remote-notification"]toios.entitlements/ios.infoPlistinapp.jsonmanually —expo prebuildwill pick them up from the config rather than from the plugin.
7. Deep links
The plugin maps your scheme (e.g. myapp) into both ios/Info.plist and android/app/src/main/AndroidManifest.xml. amba's deep-link API delivers links to your app:
To list deep links registered with amba server-side, query the deep-links module via the client SDK reference.
EAS Build env
For EAS Build to receive the project credentials + Google OAuth IDs at build time:
Use the same credentials for both profiles — environment separation is handled by the server, not the client key.
4.0 surface highlights
@layers/amba-expo re-exports the full surface of @layers/amba-react-native plus the Expo-specific helpers (Amba.signInWithApple(), Amba.signInWithGoogle({...}), Amba.registerPushToken()). The shared 4.0 namespaces:
Common pitfalls
- Forgot to re-prebuild after plugin changes — running
npx expo prebuild --cleanafter editingapp.jsonis mandatory. Otherwise the entitlements / Info.plist won't reflect the new config and push registration fails silently. - APNs key mismatch — the APNs key configured via
amba_integrations_configure(providerapns) must carry thebundle_idset inapp.json'sios.bundleIdentifier. If they drift, push token registration returns 200 but server-side delivery 404s. - Google OAuth client IDs across environments — each EAS build profile needs its own client ID matching the bundle ID for that profile. Reusing the dev client ID in production builds fails with
invalid_client. - Plugin pinned to wrong amba SDK version — when bumping
@layers/amba-expo, runnpx expo install --checkto align peer versions, then re-prebuild.
See also
- React Native SDK — the runtime layer this package wraps.
- Push notifications — campaign API, scheduling, fan-out.
- Client API reference — HTTP endpoint reference for every namespace.
- Code samples — same operations side-by-side with the other 7 SDKs.