Skip to content

Roxy-Apps/RoxyNFCScanner

Repository files navigation

RoxyNFCScanner

RoxyNFCScanner is a Swift Package for host-controlled NFC passport and ID scanning on iOS. Your app collects the MRZ input, starts the scan from its own UI, and receives the result through a delegate.

Requirements

  • iOS 14+ for CoreNFC scan flows
  • Swift 5+ (swift-tools-version: 5.10)
  • Xcode 16+

Developed with Xcode 26.3 and Swift 6.2.

This project was vibe coded with OpenAI Codex and Claude Code.

Installation

Add the package to Xcode with the repository URL, then import RoxyNFCScanner in the host app target that starts scans.

Notes

  • CSCA certificate setup is only for passive authentication.
  • If you do not provide a CSCA source URL, scanning still works and passive authentication is reported as unavailable.
  • If you do provide one, it must be a PEM source from a local file URL or an HTTPS URL.
  • The CSCA source can be a master list PEM, a single country-specific CSCA PEM, or a PEM bundle covering one or more countries.
  • Card testing is still limited. Different passports, IDs, devices, and iOS versions may behave differently.

Quick Start

The basic host flow is:

  1. Collect MRZ input.
  2. Create ScanConfiguration.
  3. Call RoxyNFCScanner.start(...).
  4. Handle completion, failure, or cancellation in RoxyNFCScannerDelegate.

Example:

import UIKit
import RoxyNFCScanner

final class ViewController: UIViewController, RoxyNFCScannerDelegate {
    @objc
    private func startNFCScan() {
        do {
            let mrzInput = try MRZKeyInput(
                documentNumber: "X00000003",
                dateOfBirth: "900103",
                expiryDate: "300103"
            )
            let scanConfiguration = ScanConfiguration()

            try RoxyNFCScanner.start(
                mrzInput: mrzInput,
                scanConfiguration: scanConfiguration,
                delegate: self
            )
        } catch let error as ScannerError {
            // Handle pre-start rejection or invalid input.
        } catch {
            // Handle non-scanner setup errors.
        }
    }

    func didFailScan(event: ScanFailureEvent) {}
    func didCompleteScan(result: DocumentDataResult) {}
    func didCancelScan() {}
}

To enable passive authentication for a scan, create the configuration with ScanConfiguration(cscaCertificateSourceURL: yourPEMURL).

RoxyNFCScanner.start(...) throws only before an attempt exists. After a scan starts, the package emits exactly one terminal delegate callback: completion, failure, or cancellation.

Public API

Use these types directly from the host app:

  • RoxyNFCScanner.start(mrzInput:scanConfiguration:delegate:)
  • MRZKeyInput
  • ScanConfiguration
  • RoxyNFCScannerDelegate
  • ScannerError
  • ScanFailureEvent
  • DocumentDataResult

Result Notes

  • DocumentDataResult can still be successful even if some DGs are missing, unsupported, or failed.
  • result.authenticationReport.passiveAuthentication.status can be passed, failed, or unavailable.
  • unavailable means passive authentication was not attempted, usually because no CSCA source was configured.
  • result.authenticationReport.activeAuthentication.status can also be unavailable depending on chip support.

Outcome Handling

  • ScannerError from start(...) means the scan never started.
  • didFailScan(event:), didCompleteScan(result:), and didCancelScan() are mutually exclusive terminal callbacks.
  • Start rejection is reported as ScannerError.startRejected(rejection:).

Example App

The reference host flow lives in Example/Example/ViewController.swift.

About

RoxyNFCScanner is a Swift Package for host-controlled NFC passport and ID scanning on iOS.

Resources

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors