npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@owl-eyes/react-native-nfc

v1.0.8

Published

React Native NFC passport reading SDK for Owl Eyes identity verification

Downloads

853

Readme

@owl-eyes/react-native-nfc

React Native NFC passport reading SDK for Owl Eyes identity verification.

Cross-platform bridge to native Android and iOS NFC passport reading libraries.

Features

  • 🔐 BAC/PACE Authentication - Automatic protocol selection
  • 📖 Data Group Reading - DG1-DG16, SOD, COM
  • Passive Authentication - SOD signature verification
  • 🛡️ Active Authentication - Chip authenticity verification
  • 🔒 Chip Authentication - Clone detection
  • 📱 Cross-Platform - iOS 14+ and Android 7+
  • React Hooks - Easy integration with React Native apps
  • 📊 Progress Events - Real-time progress updates
  • 🎯 TypeScript - Full type safety

Installation

# Using npm
npm install @owl-eyes/react-native-nfc

# Using yarn
yarn add @owl-eyes/react-native-nfc

iOS Setup

  1. Add NFC entitlements to your app:
<!-- ios/YourApp/YourApp.entitlements -->
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
    <string>A0000002471001</string>
</array>
  1. Add NFC usage description to Info.plist:
<key>NFCReaderUsageDescription</key>
<string>We need NFC access to read your passport chip for identity verification.</string>
  1. Install pods:
cd ios && pod install

Android Setup

  1. Add NFC permissions to AndroidManifest.xml:
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
  1. The SDK automatically enables NFC foreground dispatch.

Quick Start

import { OwlEyesNFC } from '@owl-eyes/react-native-nfc';

// Check NFC availability
const isSupported = await OwlEyesNFC.isNFCSupported();
const isEnabled = await OwlEyesNFC.isNFCEnabled();

if (!isEnabled) {
  await OwlEyesNFC.openNFCSettings();
}

// Read passport
const result = await OwlEyesNFC.readPassport({
  documentNumber: '123456789',
  dateOfBirth: '1990-01-15',    // YYYY-MM-DD
  dateOfExpiry: '2028-01-15',
  includeImages: true,
});

if (result.success) {
  console.log('Name:', result.data?.mrz.firstName);
  console.log('Passive Auth:', result.data?.passiveAuthPassed);
  console.log('Active Auth:', result.data?.activeAuthPassed);
}

Using React Hooks

useNFCReader

Full-featured hook for managing NFC reader state:

import { useNFCReader } from '@owl-eyes/react-native-nfc';

function PassportReader() {
  const {
    isAvailable,
    isEnabled,
    isReading,
    progress,
    result,
    readPassport,
    openSettings,
  } = useNFCReader();

  if (!isAvailable) {
    return <Text>NFC not available on this device</Text>;
  }

  if (!isEnabled) {
    return (
      <Button title="Enable NFC" onPress={openSettings} />
    );
  }

  return (
    <View>
      <Button
        title="Scan Passport"
        disabled={isReading}
        onPress={() => readPassport({
          documentNumber: '123456789',
          dateOfBirth: '1990-01-15',
          dateOfExpiry: '2028-01-15',
        })}
      />
      
      {isReading && (
        <View>
          <ProgressBar progress={progress?.progress ?? 0} />
          <Text>{progress?.message}</Text>
        </View>
      )}
      
      {result?.success && (
        <Text>Name: {result.data?.mrz.firstName}</Text>
      )}
    </View>
  );
}

usePassportRead

Simplified hook focused on the read operation:

import { usePassportRead } from '@owl-eyes/react-native-nfc';

function PassportScanner() {
  const {
    state,      // 'idle' | 'waiting' | 'reading' | 'complete' | 'error'
    progress,   // 0-100
    message,
    passport,
    error,
    read,
    cancel,
    reset,
  } = usePassportRead();

  // ... render based on state
}

useNFCState

Simple hook for monitoring NFC availability:

import { useNFCState } from '@owl-eyes/react-native-nfc';

function App() {
  const { availability, isReady, isLoading } = useNFCState();

  if (isLoading) {
    return <ActivityIndicator />;
  }

  if (!isReady) {
    return <NFCNotAvailableScreen />;
  }

  return <PassportReaderScreen />;
}

API Reference

OwlEyesNFC

Methods

| Method | Description | |--------|-------------| | isNFCSupported() | Check if device has NFC hardware | | isNFCEnabled() | Check if NFC is enabled | | getCapabilities() | Get detailed NFC capabilities | | openNFCSettings() | Open device NFC settings | | readPassport(options) | Read passport via NFC | | cancelRead() | Cancel ongoing read | | fetchCertificates(countryCode?) | Pre-fetch CSCA certificates | | hasCertificates() | Check if certificates are loaded | | clearCertificates() | Clear cached certificates |

NFCReadOptions

interface NFCReadOptions {
  documentNumber: string;       // Passport number
  dateOfBirth: string;         // YYYY-MM-DD
  dateOfExpiry: string;        // YYYY-MM-DD
  includeImages?: boolean;     // Include face/signature images
  performActiveAuth?: boolean; // Attempt Active Authentication
  performChipAuth?: boolean;   // Attempt Chip Authentication
  timeout?: number;            // Timeout in milliseconds
  dataGroups?: DataGroupSelection[]; // Specific data groups to read
}

NFCReadResult

interface NFCReadResult {
  success: boolean;
  data?: {
    mrz: MRZData;
    faceImage?: string;        // Base64
    signatureImage?: string;   // Base64
    passiveAuthPassed: boolean;
    activeAuthPassed?: boolean;
    chipAuthPassed?: boolean;
    documentInfo: DocumentInfo;
  };
  error?: NFCError;
  readTimeMs?: number;
  protocolUsed?: 'BAC' | 'PACE';
}

Event Emitter

Subscribe to NFC events:

import { NFCEventEmitter } from '@owl-eyes/react-native-nfc';

// NFC state changes (Android)
const unsubscribe1 = NFCEventEmitter.addStateChangeListener((event) => {
  console.log('NFC enabled:', event.enabled);
});

// Progress updates
const unsubscribe2 = NFCEventEmitter.addProgressListener((progress) => {
  console.log(`${progress.stage}: ${progress.progress}%`);
});

// Tag detected
const unsubscribe3 = NFCEventEmitter.addTagDetectedListener((event) => {
  console.log('Tag detected:', event.isISODEP);
});

// Clean up
unsubscribe1();
unsubscribe2();
unsubscribe3();

Utility Functions

MRZ Helpers

import {
  formatDateForMRZ,
  parseDateFromMRZ,
  validateMRZInput,
  sanitizeDocumentNumber,
} from '@owl-eyes/react-native-nfc';

// Format date for BAC/PACE key
const dob = formatDateForMRZ('1990-01-15'); // '900115'

// Parse MRZ date
const date = parseDateFromMRZ('900115'); // Date object

// Validate inputs
const error = validateMRZInput('123456789', '1990-01-15', '2028-01-15');
if (error) {
  console.error(error);
}

// Clean document number
const docNum = sanitizeDocumentNumber('AB<123456<'); // 'AB123456'

Error Handling

import { NFC_ERROR_CODES } from '@owl-eyes/react-native-nfc';

const result = await OwlEyesNFC.readPassport(options);

if (!result.success) {
  switch (result.error?.code) {
    case NFC_ERROR_CODES.TAG_LOST:
      // Ask user to hold steady
      break;
    case NFC_ERROR_CODES.BAC_FAILED:
      // Check document details
      break;
    case NFC_ERROR_CODES.PASSIVE_AUTH_FAILED:
      // Document may be tampered
      break;
  }
}

Testing

Device Requirements

  • Android: Any device with NFC (API 24+)
  • iOS: iPhone 7 or later (iOS 14+)

Testing Guide

  1. Use real passports with NFC chips for testing
  2. Test both BAC-only and PACE passports
  3. Test expired passports (chips still work)
  4. Test with various countries' passports

See Testing Documentation for detailed testing procedures.

Troubleshooting

Common Issues

"Tag lost" errors

  • Hold the device steady against the passport
  • Try different positioning (passport photo page)
  • Remove phone case if thick

BAC authentication fails

  • Verify document number, DOB, and expiry are correct
  • Check for OCR errors in MRZ reading
  • Some documents use "filler" characters (<) - try without them

NFC not detected

  • Ensure NFC is enabled in device settings
  • Check that the passport has an NFC chip (look for the chip symbol)
  • Try positioning the phone differently

License

MIT

Links