Skip to content

This repository contains the EUDI Wallet Kit library for iOS. The library is a part of the EUDI Wallet Reference Implementation project.

License

Notifications You must be signed in to change notification settings

eu-digital-identity-wallet/eudi-lib-ios-wallet-kit

EUDI Wallet Kit library for iOS

Important! Before you proceed, please read the EUDI Wallet Reference Implementation project description


EUDI ISO iOS Wallet Kit library

License Swift Lines of Code Duplicated Lines (%) Reliability Rating Vulnerabilities

Overview

This repository contains the EUDI Wallet Kit library for iOS. The library is a part of the EUDI Wallet Reference Implementation project.

This library acts as a coordinator by orchestrating the various components that are required to implement the EUDI Wallet functionality. On top of that, it provides a simplified API that can be used by the application to implement the EUDI Wallet functionality.

graph TD;
    A[eudi-lib-ios-wallet-kit]
    B[eudi-lib-ios-wallet-storage] -->  |Wallet Storage|A 
    C[eudi-lib-ios-iso18013-data-transfer] --> |Transfer Manager|A 
    D[eudi-lib-ios-openid4vci-swift] --> |OpenId4Vci Manager|A 
    E[eudi-lib-ios-siop-openid4vp-swift] --> |OpenId4Vp Manager|A 
    F[eudi-lib-ios-iso18013-security] --> |Mdoc Security|C 
    G[eudi-lib-ios-iso18013-data-model] --> |Mdoc Data Model|C 
    H[eudi-lib-ios-presentation-exchange-swift] --> E 
Loading

The library provides the following functionality:

  • Document management
    • Storage encryption
    • Using iOS Secure Enclave for generating/storing documents' keypair
    • Enforcing device user authentication when retrieving documents' private keys
  • Document issuance
    • Support for OpenId4VCI document issuance
      • Authorization Code Flow
      • Pre-authorization Code Flow
      • Support for mso_mdoc format
      • Support for sd-jwt-vc format
      • Support credential offer
      • Support for DPoP JWT in authorization
      • Support for JWT and CWT proof types
      • Support for deferred issuing
  • Proximity document presentation
    • Support for ISO-18013-5 device retrieval
      • QR device engagement
      • BLE data transfer
  • Remote document presentation
    • OpenId4VP document transfer
      • For pre-registered verifiers
      • Dynamic registration of verifiers

The library is written in Swift and is compatible with iOS 14 or higher. It is distributed as a Swift package and can be included in any iOS project.

It is based on the following specifications:

  • ISO/IEC 18013-5 – Published
  • Presentation Exchange v2.0.0 - Published
  • OpenID4VP – Draft 18
  • SIOPv2 – Draft

Disclaimer

The released software is a initial development release version:

  • The initial development release is an early endeavor reflecting the efforts of a short timeboxed period, and by no means can be considered as the final product.
  • The initial development release may be changed substantially over time, might introduce new features but also may change or remove existing ones, potentially breaking compatibility with your existing code.
  • The initial development release is limited in functional scope.
  • The initial development release may contain errors or design flaws and other problems that could cause system or other failures and data loss.
  • The initial development release has reduced security, privacy, availability, and reliability standards relative to future releases. This could make the software slower, less reliable, or more vulnerable to attacks than mature software.
  • The initial development release is not yet comprehensively documented.
  • Users of the software must perform sufficient engineering and additional testing in order to properly evaluate their application and determine whether any of the open-sourced components is suitable for use in that application.
  • We strongly recommend to not put this version of the software into production use.
  • Only the latest version of the software will be supported

Installation

To use EUDI Wallet Kit, add the following dependency to your Package.swift:

dependencies: [
    .package(url: "https://github.com/eu-digital-identity-wallet/eudi-lib-ios-wallet-kit.git", .upToNextMajor(from: "0.6.6"))
]

Then add the Eudi Wallet package to your target's dependencies:

dependencies: [
    .product(name: "EudiWalletKit", package: "eudi-lib-ios-wallet-kit"),
]

Reference

Detailed documentation is provided in the DocC documentation here

Initialization

The EudiWallet class provides a unified API for the two user attestation presentation flows. It is initialized with a document storage manager instance. For SwiftUI apps, the wallet instance can be added as an environmentObject to be accessible from all views. A KeyChain implementation of document storage is available.

The wallet developer can customize cryptographic key operations by passing SecureArea instances to the wallet, otherwise the wallet-kit creates 'SecureEnclave' (default) and 'Software' secure areas. The wallet developer can specify key create options per doc-type such as curve type, secure area name, and key unlock policy.

let wallet = try! EudiWallet(serviceName: "my_wallet_app",
   trustedReaderCertificates: [Data(name: "eudi_pid_issuer_ut", ext: "der")!] )

Manage documents

The EudiWallet class provides a set of methods to work with documents.

Loading documents

The loadDocuments method returns documents with a specific status from storage.

The following example shows how to retrieve issued documents:

 public func loadDocuments() async throws {
    let documents = try await wallet.loadDocuments(status: .issued)
  }

To retrieve documents of all statuses use the loadAllDocuments method.

let documents = try await wallet.loadAllDocuments()

The loadDocument(id:status:) method returns a document with a given id and status.

The following example shows how to retrieve a document:

let document = try await wallet.loadDocument(id: documentId, status: .issued)

Storage manager

The read-only property storage is an instance of a StorageManager class. Currently the keychain implementation is used. It provides document management functionality using the iOS KeyChain.

The storage model provides the following models for the supported well-known document types:

DocType Model
eu.europa.ec.eudiw.pid.1 EuPidModel
org.iso.18013.5.1.mDL IsoMdlModel

Since the issued mDoc documents retrieved expose only basic metadata and the raw data, they must be decoded to the corresponding CBOR models. The library provides the StorageManager\toMdocModel function to decode document raw CBOR data to strongly-typed models conforming to MdocDecodable protocol.

The loading functions automatically update the StorageManager members. The decoded issued documents are available in the mdocModels property. The deferred and pending documents are available in the StorageManager\deferredDocuments and StorageManager\pendingDocuments properties respectively.

For other document types the GenericMdocModel is provided.

Deleting a document

The deleteDocument(id:) method that deletes a document with the given id.

The following example shows how to delete a document:

try await wallet.deleteDocument(id: documentId)

Issue document using OpenID4VCI

The library provides the functionality to issue documents using OpenID4VCI.

To issue a document using this functionality, EudiWallet must be property initialized. If userAuthenticationRequired is true, user authentication is required. The authentication prompt message has localisation key "issue_document". After issuing a document, the document data and corresponding private key are stored in the wallet storage.

Issue document by docType

When the document docType to be issued use the issueDocument(docType:format:keyOptions:) method.

  • Currently, only mso_mdoc format is supported

The following example shows how to issue an EUDI Personal ID document using OpenID4VCI:

do {
  let doc = try await userWallet.issueDocument(docType: EuPidModel.euPidDocType, format: .cbor, keyOptions: KeyOptions(secureAreaName: "SecureEnclave", accessControl: [.requireUserPresence])])
  // document has been added to wallet storage, you can display it
}
catch {
  // display error
}

Resolving Credential offer

The library provides the resolveOfferUrlDocTypes(uriOffer:) method that resolves the credential offer URI. The method returns the resolved OfferedIssuanceModel object that contains the offer's data (offered document types, issuer name and transaction code specification for pre-authorized flow). The offer's data can be displayed to the user.

The following example shows how to resolve a credential offer:

 func resolveOfferUrlDocTypes(uriOffer: String) async throws -> OfferedIssuanceModel {
    return try await wallet.resolveOfferUrlDocTypes(uriOffer: uriOffer)
  }

After user acceptance of the offer, the selected documents can be issued using the issueDocumentsByOfferUrl(offerUri:docTypes:docTypeKeyOptions:txCodeValue:format:) method. The txCodeValue parameter is not used in the case of the authorization code flow. The following example shows how to issue documents by offer URL:

 let documents = try await walletController.issueDocumentsByOfferUrl(offerUri: uri,  docTypes: docOffers,
   docTypeKeyOptions: [EuPidModel.euPidDocType : KeyOptions(secureAreaName: "SecureEnclave", accessControl: [.requireUserPresence])], format: .cbor, txCodeValue: txCodeValue )

Authorization code flow

For the authorization code flow to work, the redirect URI must be specified specified by setting the the openID4VciRedirectUri property. The user is redirected in an authorization web view to the issuer's authorization endpoint. After the user authenticates and authorizes the request, the issuer redirects the user back to the application with an authorization code. The library exchanges the authorization code for an access token and issues the document.

Pre-Authorization code flow

When Issuer supports the pre-authorization code flow, the resolved offer will also contain the corresponding information. Specifically, the txCodeSpec field in the OfferedIssuanceModel object will contain:

  • The input mode, whether it is NUMERIC or TEXT
  • The expected length of the input
  • The description of the input

From the user's perspective, the application must provide a way to input the transaction code.

After user acceptance of the offer, the selected documents can be issued using the issueDocumentsByOfferUrl(offerUri:docTypes:docTypeKeyOptions:txCodeValue:format:) method. When the transaction code is provided, the issuance process can be resumed by calling the above-mentioned method and passing the transaction code in the txCodeValue parameter.

Dynamic issuance

Wallet kit supports the Dynamic PID based issuance

After calling issueDocument(docType:format:keyOptions: KeyOptions:) or issueDocumentsByOfferUrl(offerUri:docTypes:docTypeKeyOptions:txCodeValue:format:) the wallet application need to check if the doc is pending and has a authorizePresentationUrl property. If the property is present, the application should perform the OpenID4VP presentation using the presentation URL. On success, the resumePendingIssuance(pendingDoc:, webUrl:) method should be called with the authorization URL provided by the server.

if let urlString = newDocs.last?.authorizePresentationUrl { 
	// perform openid4vp presentation using the urlString 
	// on success call resumePendingIssuance using the authorization url  

Presentation Service

The presentation service protocol abstracts the presentation flow. The BlePresentationService and OpenId4VpService classes implement the proximity and remote presentation flows respectively. The PresentationSession class is used to wrap the presentation service and provide @Published properties for SwiftUI screens. The following example code demonstrates the initialization of a SwiftUI view with a new presentation session of a selected flow type.

let session = eudiWallet.beginPresentation(flow: flow)
// pass the session to a SwiftUI view
ShareView(presentationSession: session)

On view appearance the attestations are presented with the receiveRequest method. For the BLE (proximity) case the deviceEngagement property is populated with the QR code to be displayed on the holder device.

.task {
	 if presentationSession.flow.isProximity { await presentationSession.startQrEngagement() }
	 _ = await presentationSession.receiveRequest()
}

After the request is received the presentationSession.disclosedDocuments contains the requested attested items. The selected state of the items can be modified via UI binding. Finally, the response is sent with the following code:

// Send the disclosed document items after biometric authentication (FaceID or TouchID)
// if the user cancels biometric authentication, onCancel method is called
 await presentationSession.sendResponse(userAccepted: true,
  itemsToSend: presentationSession.disclosedDocuments.items, onCancel: { dismiss() }, onSuccess: {
			if let url = $0 { 
        // handle URL
       }
		})

Logging

The SwiftLog library is used for logging. The library provides a default logger that logs to the console. The main app configures logging outputs such as file logging. To use the logger create a logger instance with the desired label. The logger can be used to log messages with different log levels.

import Logging
// Create a logger with a label
let logger = Logger(label: "com.example.BestExampleApp.main")
// log an info message
logger.info("Hello World!")

Reference

Detailed documentation is provided in the DocC documentation here

Dependencies

The detailed functionality of the wallet kit is implemented in the following Swift Packages: MdocDataModel18013, MdocSecurity18013, MdocDataTransfer18013 and SiopOpenID4VP OpenID4VCI

Reference application

A reference application that demonstrates the usage of this library is App Wallet UI.

How to contribute

We welcome contributions to this project. To ensure that the process is smooth for everyone involved, follow the guidelines found in CONTRIBUTING.md.

License details

Copyright (c) 2023 European Commission

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

This repository contains the EUDI Wallet Kit library for iOS. The library is a part of the EUDI Wallet Reference Implementation project.

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages