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, collect an opaque evidence blob on the device and appraise it 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.

Minimal example

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

// Keyless collector — the client holds no Root Herald credentials.
const client = getOrCreateSharedClient();

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 client holds no Root Herald credentials.
const client = new RootHeraldClient();

// 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 holds no Root Herald key of any kind. 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 evidence-collector hook and error states.

Bridge architecture

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