A hands-on iOS workshop for building a simulated ISO 18013-5 compliant mobile ID verification system.
In this workshop, participants will build PseudoIDVerifier, an iOS app that demonstrates the core concepts of mobile identity verification using two iPhones:
- Reader Phone (Verifier): Initiates verification sessions and receives identity data
- Presentment Phone (Holder): Presents credentials with selective disclosure and biometric approval
ISO 18013-5 and Apple's ID Verifier API define the following flow:
Reader Phone Presentment Phone
(Verifier) (Holder)
┌──────────────────┐ ┌──────────────────┐
│ │ │ │
[1] │ "Tap to Verify" │ NFC TAP │ NFC Tag Ready │
│ NFC Session │◄══════════════════════►│ (HCE) │
│ │ DeviceEngagement │ │
│ │ (CBOR + BLE UUID) │ │
├──────────────────┤ ├──────────────────┤
│ │ │ │
[2] │ BLE Connect │◄═══ BLE Connection ═══►│ BLE Peripheral │
│ (Central) │ using UUID from NFC │ │
│ │ │ │
[3] │ Send Request │═══ DeviceRequest ═════►│ Show Request │
│ (CBOR) │ │ (Disclosure UI) │
│ │ │ │
[4] │ │ │ Face ID Auth │
│ │ │ Touch ID Auth │
│ │ │ │
[5] │ Receive │◄══ DeviceResponse ════│ Send Response │
│ (CBOR + mdoc) │ │ (filtered mdoc) │
│ │ │ │
[6] │ CBOR Decode │ │ │
│ Display Key-Values │ │ │
└──────────────────┘ └──────────────────┘
Step [1] NFC TAP in the flow above cannot be implemented in third-party apps:
| Feature | Status on iOS | This Workshop |
|---|---|---|
| NFC Tag Reading (Reader) | Possible with NFCNDEFReaderSession |
Reference implementation provided |
| NFC Tag Emulation (Holder) | HCE available since iOS 18.2 via NFC & SE Platform, but requires entitlement request to Apple; unclear if general developers can obtain approval | Substituted with direct BLE connection |
CardSession (iOS 17.4+) |
EEA only / payment use only | Out of scope |
| Apple ID Verifier API | ProximityReader framework / dedicated entitlement required |
Concepts explained |
Why Apple's ID Verifier API works:
- Reader side:
ProximityReaderperforms NFC polling via Enhanced Contactless Polling (ECP) - Holder side: Apple Wallet returns
DeviceEngagementas an NDEF tag at the system level - Both are Apple's proprietary implementation -- cannot be reproduced by third parties
Instead of NFC tag emulation, we use direct BLE connection:
Reader Phone Presentment Phone
(Verifier) (Holder)
┌──────────────────┐ ┌──────────────────┐
│ │ │ │
[1] │ "Tap to Verify" │ │ "Present ID" │
│ BLE Scanning │ │ BLE Advertising │
│ │ │ │
[2] │ BLE Connect │◄═══ BLE Connection ═══►│ BLE Peripheral │
│ (Central) │ │ │
│ │ │ │
[3] │ Send Request │═══ DeviceRequest ═════►│ Show Request │
│ (CBOR) │ │ (Disclosure UI) │
│ │ │ │
[4] │ │ │ Face ID Auth │
│ │ │ │
[5] │ Receive │◄══ DeviceResponse ════│ Send Response │
│ (CBOR + mdoc) │ │ (filtered mdoc) │
│ │ │ │
[6] │ CBOR Decode │ │ │
│ Display Key-Values │ │ │
└──────────────────┘ └──────────────────┘
All steps other than NFC tag emulation (BLE connection, CBOR encoding/decoding, selective attribute disclosure, biometric authentication) are implemented in compliance with ISO 18013-5.
arctic-workshop-2026/
├── initial/ # Starter project with TODOs
│ └── PseudoIDVerifier/
│ └── PseudoIDVerifier/
│ ├── Models/ # Data structures
│ ├── Services/ # Core functionality (TODOs here)
│ └── Views/ # SwiftUI views
├── completed/ # Reference implementation
│ └── PseudoIDVerifier/
│ └── PseudoIDVerifier/
│ ├── Models/
│ ├── Services/ # Fully implemented
│ └── Views/
└── Documentation.docc/ # Step-by-step tutorials
- Xcode 15.0 or later
- Two iPhones running iOS 17.0+
- Apple Developer account (for device testing)
- Clone this repository
- Open
initial/PseudoIDVerifier/PseudoIDVerifier.xcodeprojin Xcode - Update the bundle identifier and signing team
- Build and run on two devices
- Understanding mDL - Learn ISO 18013-5 data structures
- CBOR Encoding - Implement binary serialization
- NFC Handshake - Understand device engagement (includes learning iOS constraints)
- BLE Transport - Build the communication layer
- Selective Disclosure - Implement privacy-preserving data sharing
- Biometric Authentication - Add Face ID/Touch ID approval
- Integration Testing - Test the complete flow
Open the DocC documentation in Xcode:
cd Documentation.docc
open ../initial/PseudoIDVerifier/PseudoIDVerifier.xcodeproj
# Product > Build DocumentationOr read the markdown files directly in Documentation.docc/.
This workshop simulates the ISO 18013-5 standard for mobile driving licenses (mDL):
- mdoc: Mobile document containing identity attributes
- IssuerSigned: Attributes signed by the credential issuer
- DeviceSigned: Proof that the device holds the credential
- Selective Disclosure: Share only requested attributes
- DeviceEngagement: Connection establishment data (CBOR-encoded)
| Component | Description |
|---|---|
MDoc |
Mobile document data structure |
CBORService |
CBOR encoding/decoding |
BLEService |
Bluetooth communication (Central & Peripheral) |
NFCService |
NFC handover (Reader-side reference implementation / iOS HCE constraint) |
AuthenticationService |
Biometric approval (Face ID / Touch ID) |
CryptoService |
ECDSA signing, ECDH key agreement |
- Reader starts BLE scanning (Tap to Pay style UI)
- Holder starts BLE advertising
- Devices connect over BLE
- Reader sends
DeviceRequest(CBOR) - Holder shows selective disclosure request to user
- User approves with Face ID / Touch ID
- Holder sends
DeviceResponsewith filtered mdoc (CBOR) - Reader decodes CBOR and displays verified key-value attributes
This workshop teaches what is and isn't possible on iOS for NFC-BLE identity verification:
- BLE Central/Peripheral communication
- CBOR encoding/decoding per ISO 18013-5
- mdoc data structures (IssuerSigned, DeviceSigned)
- Selective disclosure filtering
- Face ID / Touch ID biometric approval
- DeviceRequest / DeviceResponse protocol
- NFC Tag Emulation (HCE) — Available since iOS 18.2 but requires entitlement request; general developer availability uncertain
ProximityReaderwithout entitlement — requires Apple contract- Cross-app NFC tag emulation — no public API exists
- Apple ID Verifier API (
ProximityReaderframework) - Enhanced Contactless Polling (ECP)
- NFC & SE Platform (iOS 18.2+ for HCE, requires entitlement request)
CardSession(iOS 17.4+, EEA only)
In the initial/ project, look for fatalError("TODO:") comments:
Services/CBORService.swift- CBOR encoding/decodingServices/BLEService.swift- BLE communicationServices/NFCService.swift- NFC handover (Reader-side reference implementation)Services/AuthenticationService.swift- Biometric auth
- ISO 18013-5 Standard
- Apple CoreBluetooth
- Apple CoreNFC
- Apple ProximityReader (ID Verifier)
- Apple LocalAuthentication
- SwiftCBOR Library
MIT License - See LICENSE file for details.
ARCTIC Conference 2026 - Building the Future of Digital Identity