SpruceKit
SpruceID
  • 🌲SpruceKit Introduction
    • Decentralized Identity Overview
    • Glossary
  • ⚡Quickstart
  • SpruceKit Mobile
    • SpruceKit Showcase App
      • Installation
      • Getting Started
      • Issue a Showcase Credential
      • Present a Showcase Credential
    • SpruceKit Mobile SDK
      • Introduction
      • Core Components
        • StorageManager
        • KeyManager
        • CredentialPack
        • Card
        • IsoMdlPresentation
        • mDocReader/IsomDLReader
        • Document Scanner
      • SpruceKit iOS SDK
        • Installation
        • Build a Wallet
          • Accept a W3C VC
          • Present a W3C VC
          • Present mDL in-person/offline
          • Present an mDL over the internet
        • Build a Verifier
          • Verify a W3C VC
          • Verify an mDL in-person/offline
          • Verify an mDL over the internet
      • SpruceKit Android SDK
        • Installation
        • Build a Wallet
          • Accept a W3C VC
          • Present a W3C VC
          • Present an mDL in-person/offline
          • Present an mDL over the internet
        • Build a Verifier
          • Verify a W3C VC
          • Verify an mDL in-person/offline
          • Verify an mDL over the internet
  • Verifiable Digital Credentials
    • ⚙️DIDKit
      • Installation
      • Core Concepts
      • DID Methods
      • Runtime Configuration
      • Specifications and Dependencies
      • Quickstart
      • DIDKit Packages
        • Command Line Interface
        • HTTP Server
        • Rust Crate
        • C Interface
        • Java and Android
        • Python
        • Javascript
      • DIDKit Examples
        • Core Functions (CLI)
        • Core Functions (HTTP)
        • did-web in minutes
        • Batch Generation & Verification
    • 🪪ISO mDL
      • Quickstart
      • Core Concepts
      • User Guide
  • Schema Definition Language
    • 🔗TreeLDR
      • TreeLDR Quickstart
        • First Schema
        • Compilation into JSON Schema
        • Compilation into JSON-LD Context
        • Writing a Layout
        • Simple Rust Integration
      • Types
        • Literal Types
      • Layouts
        • Primitive Layouts
        • Literal Layouts
        • Enumeration
        • Array Layout
        • References
      • Compiling
        • Schema Definition Formats
          • JSON Schema
          • JSON-LD Context
          • Resource Description Framework (RDF)
        • Programming Languages
          • Compiling to Rust
      • RDF Vocabulary
      • 💡TreeLDR Basics
        • Types and Layouts
        • Properties
        • Syntax
  • Witness for Credential Claims
    • 🔭Rebase
      • Core Library
      • Rust Client/Witness SDK
      • WASM Client SDK
      • Simple "Basic Post" Schema
      • DNS Witness Flow Schema
  • References
    • Contributing
    • Code of Conduct
Powered by GitBook
On this page
  • 1. Scanning Documents
  • Verify mdocs
  • MdocReaderView

Was this helpful?

  1. SpruceKit Mobile
  2. SpruceKit Mobile SDK
  3. SpruceKit iOS SDK
  4. Build a Verifier

Verify an mDL in-person/offline

Verify an ISO/IEC 18013-5 mDL over BlueTooth Low Energy

PreviousVerify a W3C VCNextVerify an mDL over the internet

Last updated 2 months ago

Was this helpful?

This guide is for iOS applications. Building for Android? Look here Verify an mDL in-person/offline

The structure for verifying an mDL is very similar to implementing the . To verify an mDL over BLE you will need to manage the BLEReaderSessionState and provide a UI for every state during the presentation process.

1. Scanning Documents

Rather than generating a QR-code, for a verifier, you will have to implement a scanning ability. For mdoc verification, you can directly use the QRCodeScanner. If you want to implement a generic scanner that can handle PDF417 VC Barcodes and Machine Readable Zones, check out this example of a .

Verify mdocs

Here, we give an example of what your VerifyMdocView could look like. You can also directly reference our implementation.

import SpruceIDMobileSdk

// An Example View for Verification of Mdocs 
public struct VerifyMDocView: View {
    @Binding var path: NavigationPath
    @State private var scanned: String?
    
    public var body: some View {
        if scanned == nil {
            QRCodeScanner(
                        title: "Scan QR Code",
                        subtitle: "Looking...",
                        onRead: { code in
                        self.scanned = code
                        },
                        onCancel: onCancel,
                        titleFont: .customFont(font: .inter, style: .bold, size: .h0),
                        subtitleFont: .customFont(font: .inter, style: .bold, size: .h4),
                        cancelButtonFont: .customFont(font: .inter, style: .medium, size: .h3),
                        readerColor: .white
            )
        } else {
            // Define an MdocReaderView and initiate it when the code is scanned
            MDocReaderView(
                // Set the scanned value
                uri: scanned!,
                // Define the items you want to query by namespace, attribute_name 
                // and intent to retain:
                requestedItems: ["org.iso.18013.5.1": ["given_name": true]],
                // Enter an array of issuer certificates that you accept (e.g. a list of US states).
                // These issuer certificates should follow the IACA profile as defined in ISO/IEC 18013-5 Annex B. 
                trustAnchorRegistry: [<issuer_cert>],
                onCancel: onCancel,
                path: $path
            )
        }
    }
    
    func onCancel() {
        // Define what to do when a user cancels the scan
        self.scanned = nil
        path.removeLast()
    }
}

MdocReaderView

Build the Delegate that holds the BLEReaderSessionState and the mDocReader sessionManager.

// Build out your Reader Delegate

class MDocReaderDelegate: ObservableObject {
    @Published var state: BLEReaderSessionState = .advertizing
    private var mdocReader: MDocReader?
    
    init(
        uri: String,
        requestedItems: [String: [String: Bool]], 
        trustAnchorRegistry: [String]?
    ) {
        // MdocReader is a core SpruceKit Component.
        self.mdocReader = MDocReader(
            callback: self,
            uri: uri,
            requestedItems: requestedItems,
            trustAnchorRegistry: trustAnchorRegistry
        )
    }
    
    func cancel() {
        self.mdocReader?.cancel()
    }
}

// Make sure to extend the BLEReaderSessionStateDelegate to MdocReaderDelegate
extension MDocReaderDelegate: BLEReaderSessionStateDelegate {
    public func update(state: BLEReaderSessionState) {
        self.state = state
    }
}

Once you have your Delegate implemented, you can add it to your MdocReaderView, which manages the UI based on the SessionState.

// Build your MdocReaderView
public struct MDocReaderView: View {
    @StateObject var delegate: MDocScanViewDelegate
    @Binding var path: NavigationPath
    var onCancel: () -> Void
    
    init(
        uri: String,
        requestedItems: [String: [String: Bool]],
        trustAnchorRegistry: [String]?,
        onCancel: @escaping () -> Void,
        path: Binding<NavigationPath>
    ) {
        self._delegate = StateObject(
            wrappedValue: MDocReaderDelegate(
                uri: uri,
                requestedItems: requestedItems,
                trustAnchorRegistry: trustAnchorRegistry
            )
        )
        self.onCancel = onCancel
        self._path = path
    }
    
    @ViewBuilder
    var cancelButton: some View {
        Button("Cancel") {
            self.cancel()
        }
        .padding(10)
        .buttonStyle(.bordered)
        .tint(.red)
 
    
    public var body: some View {
        VStack {
            switch self.delegate.state {
                // Manage the BLE ReaderSessionStates here
            }
        }
        .padding(.all, 30)
        .navigationBarBackButtonHidden(true)
    }
    
    func cancel() {
        self.delegate.cancel()
        self.onCancel()
    }
}

There you have it, you now have everything you need for an mDL verification flow. You can:

  • Initiate a QR Code Scanner

  • Manage the states of the BleReaderSession with appropriate UI of your design

  • Configure your own TrustAnchors

  • Call the MdocReader component to verify the mdoc

presentation of an mDL
Scanning Component
example