Skip to content

mCodex/react-native-sensitive-info

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

553 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

react-native-sensitive-info

npm version npm downloads Coverage License: MIT

Hardware-backed secure storage for React Native. Secrets are encrypted with AES-GCM, gated by biometrics or device credentials, and stored in the system Keychain (iOS/Apple) or Android Keystore โ€” all behind a simple Promise-based API and first-class React hooks.

Note

Upgrading from v5? See MIGRATION.md. v6 requires the New Architecture (RN 0.76+) and react-native-nitro-modules. Windows support was removed.

Table of contents

๐Ÿงญ Platform support

Platform Minimum Notes
React Native 0.76.0 New Architecture + react-native-nitro-modules required.
iOS 13.0 Add NSFaceIDUsageDescription to Info.plist for biometrics.
macOS 11.0 Catalyst and native macOS via system keychain.
visionOS 1.0 Secure Enclave-backed; biometric UX adapts to visionOS.
watchOS 7.0 Paired-device auth; storage syncs through watchOS keychain.
Android API 23 StrongBox requires API 28+; falls back to strongest available authenticator.

โš™๏ธ Installation

npm install react-native-sensitive-info react-native-nitro-modules
# yarn add react-native-sensitive-info react-native-nitro-modules
# pnpm add react-native-sensitive-info react-native-nitro-modules

No manual linking required โ€” Nitro handles autolinking.

๐Ÿ iOS

Run pod install, then add to Info.plist if you use biometric prompts:

<key>NSFaceIDUsageDescription</key>
<string>Face ID is used to unlock secrets stored in the secure enclave.</string>

๐Ÿค– Android

Add to AndroidManifest.xml:

<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />

๐Ÿงช Expo

Warning

Expo Go does not include native Nitro modules. Use a custom dev client or an EAS build.

Add the plugin to app.json, then run npx expo prebuild --clean:

{
  "expo": {
    "plugins": ["react-native-sensitive-info"]
  }
}

For a full Expo walkthrough see EXPO.md.

โšก๏ธ Quick start

import { setItem, getItem, deleteItem } from 'react-native-sensitive-info'

// Write โ€” uses the strongest available security policy by default
await setItem('session-token', 'abc123', { service: 'auth' })

// Read โ€” returns value + metadata
const item = await getItem('session-token', { service: 'auth' })
console.log(item?.value)                  // 'abc123'
console.log(item?.metadata.securityLevel) // e.g. 'secureEnclave'

// Remove
await deleteItem('session-token', { service: 'auth' })

Building a component? The hooks API handles loading states, cleanup, and error boundaries โ€” no useEffect boilerplate needed.

โš›๏ธ React Hooks API (Recommended)

import { Text, View, ActivityIndicator } from 'react-native'
import {
  useSecureStorage,
  useSecurityAvailability,
} from 'react-native-sensitive-info/hooks'

function SecretsView() {
  const { items, isLoading, error, saveSecret, removeSecret } =
    useSecureStorage({ service: 'myapp', includeValues: true })
  const { data: capabilities } = useSecurityAvailability()

  if (isLoading) return <ActivityIndicator />
  if (error) return <Text>Error: {error.message}</Text>

  return (
    <View>
      {items.map(item => (
        <Text key={item.key}>
          {item.key}: {item.value} ({item.metadata.securityLevel})
        </Text>
      ))}
      <Text>Biometry: {capabilities?.biometry ? 'available' : 'unavailable'}</Text>
    </View>
  )
}
Hook Use case
useSecureStorage() List, add, and remove all secrets in a service.
useSecret() Fetch a single secret with read/write mutations.
useHasSecret() Lightweight existence check (no decryption).
useSecurityAvailability() Query device capabilities (auto-cached).
useKeyRotation() Rotate the master key for a service.
useBiometryStatusWatcher() Subscribe to biometric enrollment-state transitions.

All hooks auto-cancel in-flight requests on unmount. For advanced patterns and best practices see HOOKS.md.

๐Ÿ“š API reference

Method Description
setItem(key, value, options?) Write a secret using the strongest available security policy.
getItem(key, options?) Read a secret and its metadata. Pass includeValue: false to skip the payload.
hasItem(key, options?) Check whether a secret exists (no biometric prompt).
deleteItem(key, options?) Remove a secret. Returns true if something was deleted.
getAllItems(options?) List all secrets in a service.
clearService(options?) Remove every secret in a service namespace.
getSupportedSecurityLevels() Snapshot of device capabilities (biometrics, Secure Enclave, StrongBox, โ€ฆ).
canUseAccessControl(policy) Check whether a given access-control policy is supported on this device.
rotateKeys(options?) Bump the active key version; subsequent reads transparently re-encrypt older entries.

Common options:

Option Default Description
service bundle ID / 'default' Logical namespace for secrets.
accessControl 'secureEnclaveBiometry' Preferred write policy; native layer picks the strongest supported fallback.
authenticationPrompt โ€” Localized strings for biometric / device-credential prompts.
iosSynchronizable false Sync via iCloud Keychain.
keychainGroup โ€” Custom Keychain access group.

Errors are typed โ€” import predicates from react-native-sensitive-info/errors:

import {
  isAuthenticationCanceledError,
  isKeyInvalidatedError,
  isIntegrityViolationError,
} from 'react-native-sensitive-info/errors'

๐Ÿ›ก๏ธ Security

Every secret is encrypted with AES-GCM and bound to a hardware-protected key โ€” the Secure Enclave on Apple platforms and the Android Keystore (StrongBox when available). Each entry carries an HMAC-SHA256 integrity tag recomputed on every read; a mismatch raises IntegrityViolationError before any biometric prompt fires, so spoofed entries can never trigger user authentication.

For the full cryptographic model โ€” key derivation, AAD binding, replay defense, and threat classification โ€” see THREAT_MODEL.md.

๐ŸŒณ Tree-shaking

All entry points are side-effect-free ("sideEffects": false). Import only what you use:

Subpath Contents
react-native-sensitive-info Core API (setItem, getItem, hasItem, deleteItem, getAllItems, clearService, rotateKeys, โ€ฆ)
react-native-sensitive-info/hooks React hooks (useSecureStorage, useSecret, useKeyRotation, โ€ฆ)
react-native-sensitive-info/errors Typed error classes and instanceof predicates

๐ŸŽฎ Example app

cd example && yarn install

yarn ios      # iOS
yarn android  # Android

๐Ÿ› ๏ธ Development

yarn install    # Install dependencies
yarn codegen    # Regenerate Nitro bindings
yarn typecheck  # Type-check sources
yarn build      # Build distributable packages

๐Ÿฉบ Troubleshooting

  • Biometric prompt never appears โ€” use canUseAccessControl(policy) to check before writing and fall back to devicePasscode if needed.
  • authentication failed on simulator โ€” Secure Enclave and StrongBox are unavailable on simulators. Validate biometric policies on physical hardware.
  • E_AUTH_CANCELED in error message โ€” the user dismissed the prompt. Handle gracefully; hook state is not poisoned by cancellations.
  • Undefined symbol on iOS โ€” re-run pod install after upgrading to v6.

๐Ÿค Contributing

Contributions are welcome!

  • ๐Ÿ› Bugs โ€” Open an issue with a minimal reproduction. Security vulnerabilities should be reported privately โ€” see SECURITY.md.
  • ๐Ÿ’ก New features โ€” Open an issue first to align on scope before writing code.
  • ๐Ÿ”€ Pull requests โ€” Run yarn test and yarn typecheck before submitting. Keep changes focused and reference the relevant issue.

Please review CODE_OF_CONDUCT.md before contributing.

๐Ÿ“„ License

MIT ยฉ Mateus Andrade

About

๐Ÿ” React Native secure storage, rebuilt with Nitro Modules โšก๏ธ Biometric-ready, StrongBox-aware, and metadata-rich for modern mobile apps

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Contributors