On this page
Implementation guide
Integrate without changing your transport
The SDK collects locally. Your application decides when to collect and how to send the event through its existing authenticated API.
Requirements
| React Native | 0.76 or newer, New Architecture enabled |
|---|---|
| Android | API 24 or newer |
| iOS | CocoaPods and the minimum iOS version supported by the host React Native release |
| Expo | Native prebuild or custom development build; Expo Go is not supported |
Install
npm install react-native-device-risk-signals
npx pod-installUse the repository package manager and existing Bundler workflow when applicable. Autolinking registers the native module.
Expo prebuild and development builds
Use this package only in an Expo project that already uses native prebuild or a custom development client. Expo Go cannot load the TurboModule.
- Confirm the project uses React Native 0.76 or newer and does not disable the New Architecture.
- Install the package with Expo's version-aware installer:
npx expo install react-native-device-risk-signals- After adding or upgrading the package, run
npx expo prebuild --cleanwhenandroid/andios/are generated with Continuous Native Generation. A clean prebuild is the safest way to synchronize native code and is generally recommended for CNG-managed directories. It deletes and recreatesandroid/andios/, so preserve manual changes first and do not use it over manually maintained native projects. - If the repository keeps an existing
ios/project and does not regenerate it, install CocoaPods with its established command, such asnpx pod-installorbundle exec pod install. A normal iOS prebuild installs pods unless it is run with--no-install. - Create and install a new native binary with
npx expo run:android,npx expo run:ios, or the project's existing EAS development-build profile. Metro reloads and over-the-air updates cannot add this native module to an already-built client.
After the native module is present, JavaScript-only application changes do not require another prebuild. Regenerate and rebuild when this package, Expo, React Native, or other native configuration changes.
Configure purpose and consent
Start with the smallest set that serves a documented purpose. Consent is subtractive: it can remove probes from collection, not silently enable additional ones.
import { consentFor, DeviceIntel } from "react-native-device-risk-signals";
const deviceIntel = new DeviceIntel({
sessionId: session.id,
consent: consentFor([
"device_identity",
"application",
"os_integrity",
"device_security_posture",
"runtime",
]),
probes: {
network: { enabled: false },
geolocation: { enabled: false },
transaction_safety: { enabled: false },
},
});Host permission matrix
The library manifest declares no permissions and the SDK never displays a permission prompt. It uses sensitive access only when the host application has already declared or received it.
| Host access | Probe and fields | Behavior when unavailable |
|---|---|---|
ACCESS_NETWORK_STATE | network: active transports, validation, captive portal, DNS, Private DNS, MTU, and link estimates | Permission-dependent fields are omitted. No network request is made. |
READ_PHONE_STATE already granted | telephony.simCount | The field is omitted. The SDK never requests phone-state permission. |
| Location permission already granted | geolocation: cached coordinates, accuracy, provider, age, and mock-source state | Cached-location fields are omitted. The SDK never requests location permission or starts active updates. |
BLUETOOTH_CONNECT already granted | media_bluetooth_apps.bluetoothBondedDeviceCount | The count is omitted. No Bluetooth permission prompt is displayed. |
DETECT_SCREEN_CAPTURE on Android 14+ | transaction_safety: screenshot observation active, detected state, and elapsed time | Screenshot fields are omitted. Android shows its standard notice only after an observed screenshot. |
DETECT_SCREEN_RECORDING on Android 15+ | transaction_safety.isVisibleInScreenRecording and Android isScreenCaptured alias | Recording-visibility fields are omitted. |
Add only the permissions required by the fields your application has approved. See the typed catalog for probe-level notes and the privacy guide before production collection.
Collect at a meaningful event
Attach a server-generated session or action identifier. Avoid stable identifiers created solely for fingerprinting.
const event = await deviceIntel.collect({
sessionId: checkoutSessionId,
});
await api.post("/mobile-risk-observations", {
accountActionId,
observations: event,
});The example endpoint is owned by the host application. It is not part of this package.
Collect protected-action context separately
transaction_safety is disabled by default. On Android, the first enabled collection starts lazy screenshot and obscured-touch observation. Collect once when the protected UI opens, then collect again immediately before its action.
const transactionConfig = {
probes: {
transaction_safety: { enabled: true, timeoutMs: 900 },
},
};
await deviceIntel.collect({ config: transactionConfig });
// Later, immediately before the protected action:
const protectedActionEvent = await deviceIntel.collect({
config: transactionConfig,
});Obscured-touch flags need no permission. Android 14 screenshot detection and Android 15 recording visibility require the host application to declare DETECT_SCREEN_CAPTURE or DETECT_SCREEN_RECORDING respectively. Add only the required install-time permission to the host application's android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />
<uses-permission android:name="android.permission.DETECT_SCREEN_RECORDING" />The library declares neither permission and never prompts. Android displays its standard notice when a screenshot is detected. Missing capture fields mean the API, host permission, callback, or observation was unavailable; they do not mean capture was observed off.
Accessibility, screen-sharing, and overlays can be legitimate. Use them as review context, not an automatic accusation.
Backend contract
- Authenticate the mobile request using your normal session controls.
- Validate event schema, SDK version, collection timestamp, and action binding.
- Preserve probe outcome semantics. Missing, skipped, timeout, and error are distinct.
- Compute derived features and policy on a trusted backend.
- Apply retention, access controls, monitoring, and deletion requirements.