The NFC module reads the secure NFC chip embedded in ICAO 9303-compliant travel documents, such as e-passports. It then returns the document holder's data, including the chip's portrait image. When a flow captures multiple IDs, NFC Scan applies only to the first ID. Chip reading uses secure messaging; see Security.
For an overview of this module and how it works, see NFC Scan.
This page covers the code-configured flow: building an IncdOnboardingFlowConfiguration in your app and calling startOnboarding. When the flow is defined in Dashboard instead and started with startFlow or startWorkflow, the NFC step is configured server-side. See Integration Approaches.
This module requires the NFCReaderUsageDescription key and the ISO 7816 application identifiers. See Add Required Permissions.
Availability: The -nfc build variant, on NFC-capable devices running iOS 13 or later. Calling it from a non-NFC variant triggers a runtime variant assertion (IncdOnboardingVariant.assertIncludes(.nfc)).
UI: standalone (Apple's system NFC sheet).
Use this module when:
- You need a high-assurance read of the document chip, not just an OCR of the printed page.
- Your flow performs
.nfcSelfieor.nfc3WayFace Match against the chip photo. These match types become available whenprocessNFCDatais enabled.
Add NFC
- Build the SDK with the
-nfcvariant so the NFC module is linked in. - Add ID Capture (
addIdScan(scanStep: .both)) then Process ID (addIdProcess()), before NFC. NFC reads the chip after the document has been captured and processed. - Add the module with
addNfcScan(). All parameters are optional; omitting one falls back to its default.flowConfig.addNfcScan( idType: nil, // .id or .passport; nil uses the captured/selected type showNFCSymbolConfirmationScreen: nil, // ask the user to confirm the chip symbol (default true) showInitialDataConfirmationScreen: nil, // confirm the key data before reading (default true) showTutorials: nil, // show scanning tutorials (default true) nfcMaxRetries: nil, // retry budget (default 5) processNFCData: nil, // process the read data on the backend (default true) returnResultImmediately: nil // return as soon as the chip is read (default false) )
Example
The example below adds NFC after ID Capture and ID OCR/Process, shows the NFC symbol confirmation screen, processes the chip data, and listens for the result through the onNFCScanCompleted(_:) delegate callback.
let flow = IncdOnboardingFlowConfiguration()
flow.addIdScan(scanStep: .both)
// ID OCR runs automatically after a .both ID Capture
flow.addNfcScan(
showNFCSymbolConfirmationScreen: true,
processNFCData: true
)
IncdOnboardingManager.shared.startOnboarding(
sessionConfig: IncdOnboardingSessionConfiguration(token: "<SESSION_TOKEN>"),
flowConfig: flow,
delegate: self
)
extension MyViewController: IncdOnboardingDelegate {
func onNFCScanCompleted(_ result: NFCScanResult) {
// NFC scan completed. Process the result.
}
}
Configuration Options
Configure the module with addNfcScan().
| Option | Type | Description |
|---|---|---|
idType |
IdType? |
.id or .passport; nil uses the document already captured or selected. |
showNFCSymbolConfirmationScreen |
Bool? |
Shows a screen asking whether the document contains an NFC chip. Default: true. |
showInitialDataConfirmationScreen |
Bool? |
Confirms the key data before reading the chip. Default: true. |
showTutorials |
Bool? |
Shows tutorials on how to scan the document. Default: true. |
nfcMaxRetries |
Int? |
Sets the maximum number of NFC scan attempts. Default: 5. |
processNFCData |
Bool? |
Submits the chip data to the back end for identity validation. Enables the .nfcSelfie and .nfc3Way Face Match types. Default: true. |
returnResultImmediately |
Bool? |
Returns as soon as the chip is read. Default: false. |
For each NFC read, the SDK tries the PACE protocol first and falls back to BAC when PACE is unavailable or fails. PACE and BAC are alternatives, not both required. An NFC chip whose access protocol the device cannot complete fails the scan and routes through the retries configured using nfcMaxRetries.
Result
func onNFCScanCompleted(_ result: NFCScanResult)
NFCScanResult fields:
facePhoto: UIImage?: The document holder's face image decoded from the chip.dg1: NFCDataModel.DG1?: The machine-readable zone (MRZ) data (DG1). Its fields include:documentNumber: The nine most-significant digits of the document number.documentCode: The MRZ document code. One of the following:TD1,TD2,TD3,MRVA, orMRVB. The default isTD3.nationality: The document holder's nationality as a three-letter code.issuingStateOrOrganization: The issuing state or organization as a three-letter code.birthDate: The date of birth inyyMMddformat (DG1).expireAt: The document expiry date inyyMMddformat (DG1).gender: The document holder's gender. One of the following:MALE,FEMALE,UNKNOWN, orUNSPECIFIED.primaryIdentifier: The document holder's last name.secondaryIdentifier: The document holder's first name.optionalData1: First optional data field (ID-1 and ID-3 style MRZs).optionalData2: Second optional data field (ID-1 style MRZs only); may benull.personalNumber: Personal number, if encoded inoptionalData1.- The corresponding MRZ check-digit fields:
compositeCheckDigit: The MRZ composite check digit (DG1);<when unset.dateOfBirthCheckDigit: The check digit for the date of birth;<when unset.documentNumberCheckDigit: The check digit for the document number;<when unset.expirationDateCheckDigit: The check digit for the expiration date;<when unset.personalNumberCheckDigit: The check digit for the personal number (TD3 only); may benull.
error: NFCScanError?: Set when the scan did not complete successfully.
Errors
Errors surface on the completion callback as result.error. Wrong-variant calls fail immediately via IncdOnboardingVariant.assertIncludes(.nfc) instead of through this callback.
NFCScanError cases:
error: A wrappedIncdError.notAvailable: NFC not available on this OS/device.userDocumentHasNoChipnoScanAttemptsRemaining