@surepass/digilocker-react-native-sdk
v2.1.0
Published
React Native wrapper for Digilocker SDK (Android .aar + iOS .xcframework)
Readme
Digilocker React Native SDK
React Native wrapper for the Digilocker SDK — Aadhaar-based identity verification on Android and iOS, by SurePass.
- One JS API —
launchSDK— for both platforms - Android: prebuilt
.aar, auto-linked via React Native config - iOS: prebuilt
.xcframework, fetched atpod installand pinned by checksum - Promise-based, fully typed, with documented error codes
Requirements
| Requirement | Minimum |
| ------------------ | -------- |
| React Native | 0.80+ |
| React | 19.0+ |
| Node | 20.19.4+ |
| iOS deployment | 15.1 |
| Android minSdk | 28 |
| Android compileSdk / targetSdk | 36 |
| Swift | 5.9 |
| Java | 17 |
Installation
npm install @surepass/digilocker-react-native-sdk
# or
yarn add @surepass/digilocker-react-native-sdkiOS
cd ios && pod installThat's all — no Info.plist entries and no runtime permissions are required.
pod install downloads DigilockerSDK.xcframework (~1.5 MB) and caches it, so
the first install on a machine needs network access.
Android
Autolinking handles the module itself. One project change is required:
android/build.gradle — raise minSdkVersion to 28. React Native's
template defaults to 24, and the .aar declares
<uses-sdk android:minSdkVersion="28" />, so a lower value fails manifest
merging.
buildscript {
ext {
minSdkVersion = 28
// ...
}
}Nothing else. No tools:replace, no manifest edits, no ProGuard rules — see
Android details for what the SDK contributes on its own.
Quick Start
import { launchSDK } from '@surepass/digilocker-react-native-sdk';
try {
const result = await launchSDK('<your-token>', 'PREPROD');
if (result.success) {
// iOS → result.clientId
// Android → result.signedResponse, result.status_code
console.log('Verified!', result.clientId ?? result.signedResponse);
} else {
console.warn('Verification failed:', result.error);
}
} catch (e: any) {
switch (e.code) {
case 'USER_CANCELLED':
console.log('User backed out (Android)');
break;
case 'SDK_ERROR':
console.log('SDK error (iOS):', e.message);
break;
default:
console.error('Unexpected error:', e);
}
}Token: get a bearer token from the Digilocker Initialize API before calling
launchSDK. Generate it server-side — it needs your API key, which should never ship inside a mobile app.
Handle both failure paths, on both platforms
The two platforms report the same failure on different branches of the promise. An invalid token gives you:
| Platform | Outcome |
| -------- | ------- |
| iOS | Rejects — code: 'SDK_ERROR', "Your access token is invalid" |
| Android | Resolves — success: false, status_code: 401, message inside signedResponse |
So always check result.success and wrap the call in try/catch, as the
Quick Start does. Treating a resolved promise as proof of success works on iOS
and silently swallows failures on Android.
API Reference
launchSDK(token, env)
| Parameter | Type | Description |
| --------- | ------------- | ---------------------------------------- |
| token | string | Bearer token from the Initialize API |
| env | Environment | 'PREPROD' (sandbox) or 'PROD' (live) |
Returns: Promise<SDKResult>
SDKResult
| Field | Type | Platform | Description |
| ---------------- | --------- | -------- | ----------------------------------------------- |
| success | boolean | Both | Whether verification completed successfully |
| clientId | string? | iOS | Client ID for the Download Aadhaar API |
| signedResponse | string? | Android | Raw signed JSON string from the SDK |
| status_code | number? | Android | HTTP-style status code from the SDK response |
| error | string? | Both | Error message when success is false |
Error codes
Values of e.code on a rejected promise.
| Code | Platform | Meaning |
| -------------------- | -------- | ------------------------------------------ |
| USER_CANCELLED | Android | User pressed back / cancelled the flow |
| SDK_BUSY | Android | Another SDK session is already running |
| NO_ACTIVITY | Android | No current activity — app not foregrounded |
| LAUNCH_ERROR | Android | Failed to start the SDK activity |
| PARSE_ERROR | Android | SDK response was not valid JSON |
| UNKNOWN_RESULT | Android | SDK returned an unrecognised result code |
| SDK_ERROR | iOS | SDK reported a failure, or user cancelled |
| NO_VIEW_CONTROLLER | iOS | Could not find a root view controller |
Example app
example/ is a React Native 0.86 app that consumes this package
straight from the repo. Paste a token, pick an environment, launch the flow —
everything launchSDK resolves or rejects with is rendered on screen.
npm install # repo root
cd example && npm install
cd ios && pod install && cd .. # iOS only
npm run android # or: npm run iosSee example/README.md for details.
Android details
You do not need to configure any of this. It is listed so you know what the SDK adds to your app, and what it deliberately does not.
Permissions
Merged in from the .aar; none are runtime permissions, so there is no
permission prompt to handle:
INTERNET · ACCESS_NETWORK_STATE · VIBRATE
Network security
Nothing to configure. The SDK talks to *.surepass.app over https
exclusively, and it leaves your app's network security policy alone.
That is worth stating explicitly, because it was not true before 2.0.1. The
.aar declares an android:networkSecurityConfig in its own library manifest,
which merges into the consuming app and applies app-wide — even to apps that
never declared one. The config it points at has only <domain-config> blocks
for the surepass hosts and no <base-config>, so every other host fell
through to the platform default of cleartextTrafficPermitted="false".
localhost was one of those hosts, so Metro at http://localhost:8081 was
refused at the platform level and every debug build died with
Unable to load script. A Network Security Config also
overrides android:usesCleartextTraffic, so React Native's debug placeholder
could not rescue it.
Since 2.0.1 this module strips that attribute during manifest merging, which restores the platform defaults:
| | Before 2.0.1 | 2.0.1+ |
| --- | --- | --- |
| Cleartext to localhost (debug) | Blocked — Metro unreachable | Governed by your app, as normal |
| Trust anchors for *.surepass.app | System and user-installed CAs | System CAs only |
Note the second row. The .aar's config added <certificates src="user"/>,
which widened trust to user-installed CAs on KYC traffic — that is what makes
interception by a locally installed root certificate possible. Removing it is
the stricter behaviour, not the looser one.
If your app declares its own networkSecurityConfig, it is untouched by any of
this and continues to apply.
ProGuard / R8
The .aar ships its own consumer rules, applied automatically. Building with
minifyEnabled true needs no rules on your side; they cover the Gson response
models, the WebView JavaScript bridge, and the Retrofit service interfaces.
Transitive dependencies
The .aar is vendored as a bare file and carries no POM, so the wrapper
declares its runtime dependencies explicitly. Notably Retrofit 3.x,
OkHttp 5.x and Glide 5.x — if your app pins older majors of these,
Gradle will resolve to the newer version for the whole app.
androidx.core:core-ktx:1.17.0 androidx.appcompat:appcompat:1.7.1
com.google.android.material:material:1.13.0 androidx.constraintlayout:constraintlayout:2.2.1
androidx.activity:activity-ktx:1.12.3 androidx.fragment:fragment-ktx:1.6.2
androidx.lifecycle:lifecycle-runtime-ktx:2.10.0 androidx.lifecycle:lifecycle-viewmodel-ktx:2.10.0
androidx.lifecycle:lifecycle-livedata-ktx:2.10.0 androidx.navigation:navigation-fragment-ktx:2.9.7
androidx.navigation:navigation-ui-ktx:2.9.7 com.squareup.retrofit2:retrofit:3.0.0
com.squareup.retrofit2:converter-gson:3.0.0 com.squareup.okhttp3:okhttp:5.3.2
com.jakewharton.timber:timber:5.0.1 com.github.bumptech.glide:glide:5.0.5
com.getkeepsafe.taptargetview:taptargetview:1.15.0
com.google.android.gms:play-services-auth:21.5.0
com.google.android.gms:play-services-auth-api-phone:18.3.0Troubleshooting
The package '...' doesn't seem to be linked
The JS loaded but the native module did not. Rebuild — reloading Metro is not enough:
npx react-native run-android
# iOS
cd ios && pod install && cd .. && npx react-native run-iosuses-sdk:minSdkVersion 24 cannot be smaller than version 28
Raise minSdkVersion to 28 in android/build.gradle — see
Installation → Android.
Unable to load script
Unable to load script. Make sure you're running Metro or that your bundle
'index.android.bundle' is packaged correctly for release.On 2.0.0 and earlier this was usually the SDK's fault: its network security
config blocked cleartext to localhost, so Metro was unreachable no matter how
healthy it was. Fixed in 2.0.1 — see Network security. If
you are stuck on 2.0.0, the workaround is a debug-only
android/app/src/debug/res/xml/network_security_config.xml permitting cleartext
to localhost; upgrading is simpler.
On 2.0.1+ it means what it says, and the usual causes are:
- Metro is not running, or was started from the wrong directory. In a repo
where the app is a subfolder,
npm startat the root fails withMissing script: "start"and Metro never comes up. Start it from the app directory. adb reverseis not set for a physical device. Re-runadb reverse tcp:8081 tcp:8081;adb reverse --listshould show it.
To tell a genuine connection failure from a policy block, read the log:
adb logcat -d --pid=$(adb shell pidof <your.application.id>) | grep -i isMetroRunningAsync result = true means the platform reached Metro. A policy block fails in
single-digit milliseconds; an absent Metro or broken tunnel times out instead.
Manifest merger failed : Attribute application@allowBackup (or @usesCleartextTraffic)
Only affects 2.0.0 and earlier, where the .aar forced these onto the host
app. Upgrade to 2.0.1+, and you can delete the
tools:replace="android:allowBackup,android:usesCleartextTraffic" workaround
from your manifest.
no such module 'DigilockerSDK'
The framework is downloaded during pod install, not shipped in the package,
so its absence beforehand is expected. Re-run pod install from the app's
ios/ directory and check the output for a download or checksum error. If it
prints nothing, CocoaPods skipped the pod as unchanged — force it with
pod install --repo-update.
Android build fails with a missing .aar
Confirm android/libs/digilocker.aar exists in the installed package.
Changelog
See CHANGELOG.md.
