Skip to content
SDKs · React NativeComing soonView source

@rootherald/react-native

React Native bindings for Root Herald. Bridges the iOS RootHeraldKit and Android RootHeraldClient native SDKs into a JS-callable API with idiomatic React hooks. Keyless: the client collects a hardware-rooted evidence blob over a backend-issued nonce and hands it back to your app — it holds no secret and never renders a verdict. Your backend relays the blob to the verify API, which appraises it.

Coming soon — in development

This SDK is planned and not yet available. Until it ships, mint attestation tokens on the device and verify them server-side with @rootherald/node (or any available server SDK). The API shown below is the planned surface and may change before release.

Install

npmbash
npm install @rootherald/react-native
npx pod-install ios

On RN 0.72+, autolinking discovers the iOS Podspec and Android Gradle module automatically. For older RN versions, run react-native link @rootherald/react-native once after install.

Five-line example

SignupScreen.tsxtsx
import { useCollectEvidence, getOrCreateSharedClient } from '@rootherald/react-native';

// The publishable key is for site/origin attribution only — never a secret.
const client = getOrCreateSharedClient({ publishableKey: 'rh_pk_live_REPLACE_ME' });

export function SignupScreen() {
  // getNonce/relay hit YOUR backend, which owns the rh_sk_ secret and the verdict.
  const { collect, loading } = useCollectEvidence({
    client,
    getNonce: () => myBackend.getChallengeNonce('signup'),
    relay:    (evidence) => myBackend.verifyAndAuthorize('signup', evidence),
  });
  return <Button onPress={collect} disabled={loading} title="Attest device" />;
}

The hook starts idle. When the user taps the button, collect() walks the native bridge into RootHeraldKit (iOS) or RootHeraldClient (Android), collects a hardware-rooted evidence blob over the nonce, and hands it to your relay callback. The verdict is decided by your backend and never travels through the client.

Imperative client

client.tsts
import { RootHeraldClient, NotEnrolledError } from '@rootherald/react-native';

// Keyless collector. The publishable key is optional site attribution, not a secret.
const client = new RootHeraldClient({ publishableKey: 'rh_pk_live_REPLACE_ME' });

// 1. Get a fresh challenge nonce from YOUR backend (it called
//    POST /api/v1/attestations/challenge with its rh_sk_ secret).
const nonce = await myBackend.getChallengeNonce('signup');

// 2. Collect a keyless quote-over-nonce evidence blob on-device.
try {
  const evidence = await client.collectEvidence(nonce);

  // 3. Relay the blob to your backend, which POSTs it to
  //    /api/v1/attestations/verify and enforces the verdict.
  if (await myBackend.verifyAndAuthorize('signup', evidence)) {
    proceed();
  } else {
    refuse();
  }
} catch (e) {
  if (e instanceof NotEnrolledError) await client.enroll(myBackend.relayEnroll);
}

Hook behavior

  • autoStart: true fires collect() once on mount.
  • collect() is stable across renders and coalesces overlapping calls, so only the latest result wins.
  • In-flight calls are cancelled on unmount via AbortController.
  • reset() clears local state without firing a new collect.

Where the evidence goes

The client opens no socket to RootHerald and carries no secret — the only key it may hold is the rh_pk_ publishable key, used solely for site/origin attribution. It always hands the collected blob back to your own app code, which relays it to your backend. Your backend issues the nonce, POSTs the evidence to POST /api/v1/attestations/verify, and enforces the verdict — all authenticated with its rh_sk_ secret via the server SDK @rootherald/node. The secret must never reach the device.

Expo support

The bare workflow and Expo development builds are fully supported. The Expo managed workflow / Expo Gocan't load the native attestation code — use a development build on Expo SDK 50+. An Expo config plugin is planned to simplify managed-workflow setup.

Native dependencies

  • iOS: RootHeraldKit (SwiftPM), iOS 14+, App Attest entitlement required.
  • Android: io.rootherald:rootherald (Gradle), minSdk 26, AndroidKeyStore.

Sample app

A single-screen Expo bare-workflow sample ships alongside the SDK when it's released. It demonstrates the hook, error states, and a sheet to switch between Direct / Custom Domain / Reverse Proxy transport modes.

Bridge architecture

We use the legacy NativeModule pattern rather than a generated TurboModule spec; the package supports RN 0.72+.