An iOS app demonstrating inter-application signing of transactions using various EOSIO Labs specifications and technologies. Transactions can be proposed from:
- web applications running in Mobile Safari
- other native iOS apps using EOSIO SDK for Swift
Signing from Mobile Safari | Signing from Native App |
---|---|
EOSIO Labs repositories are experimental. Developers in the community are encouraged to use EOSIO Labs repositories as the basis for code and concepts to incorporate into their applications. Community members are also welcome to contribute and further develop these repositories. Since these repositories are not supported by Block.one, we may not provide responses to issue reports, pull requests, updates to functionality, or other requests from the community, and we encourage the community to take responsibility for these.
- Introduction
- Prerequisites
- Installation
- First Use
- Getting Started with an Example Web App
- Usage
- Configuring Apps to Work with EOSIO Reference iOS Authenticator App
- Architecture
- Contributing
- License & Legal
The EOSIO ecosystem is rich with existing wallets providing users the ability to sign transactions on the EOSIO blockchain. However, we have identified some limitations and possible areas for improvement to the overall user experience:
- Lack of support for chains other than Mainnet.
- Lack of support for richly displaying Ricardian Contracts.
- Lack of transparency and verification of application's identity and intentions, especially during transaction signing.
- Lack of support for inter-application transaction signing on native mobile devices. Most mobile wallets restrict integrating app developers to a mobile web application form factor and force users to access integrating apps within a blockchain-only browser.
- Dependence on users to know enough information about the chain they are transacting on to be able to set up a network in the wallet. Even more, dependence on users to know they are transacting on a blockchain in the first place.
This reference implementation is one of two examples (see also the EOSIO Reference Chrome Extension Authenticator App ) for wallet developers and presents possible solutions to the problems above using a native iOS Authenticator application. The EOSIO Reference iOS Authenticator App provides the following features, as examples:
- It enables seamless, multi-network support. In fact, the app, itself, does not even communicate with chains or nodes directly.
- It securely stores private keys and employs the use of biometrics to signs transactions.
- It displays richly-formatted Ricardian Contracts, which provide users with a human-readable explanation of the action(s) the app is proposing and allows users to approve or reject the terms of the contract(s).
- By following the Manifest Specification, the Reference Authenticator App displays metadata about the requesting application to end users any time they are prompted to trust an app or sign a transaction from one. This provides users with an improved sense of trust in the requesting application and the signing ceremony itself. The Reference Authenticator App also runs various transaction pre-flight security checks, comparing the contents of a transaction request with what integrating apps have declared about themselves.
- Reference App, Authenticator App, Reference iOS Authenticator App: This app, the EOSIO Reference iOS Authenticator App.
- Integrating App, Requesting App: Native iOS apps or web applications that request public keys or the signing of transactions from this EOSIO Reference iOS Authenticator App.
- Authenticator, Auth: Public and/or private keys.
This is just one of several thought leadership works focusing on wallets, key management and authentication, and the relating user experience. For more context and related reading, check out these these pieces:
- A Passwordless Future: Building Towards More Secure and Usable Authentication Systems
- EOSIO Authentication Transport Protocol Spec
- EOSIO Software Release: Ricardian Contract Specifications and the Ricardian Template Toolkit
- EOSIO Manifest Specification
- EOSIO Labs™ Release: The Universal Authenticator Library (UAL) — Increasing the Accessibility of Blockchain Applications
- Xcode 10+
- iOS 12+
- CocoaPods v1.5.3+
- Touch ID or Face ID must be enabled and you must be enrolled
- Clone this repo and ensure you are on the
master
branch - Run a
pod install
. - Open the
.xcworkspace
in Xcode. - Change the bundle identifier from
one.block.eosio
to a new bundle identifer of your choice. - Under
Capabilities, App Groups
, select an app group from your Apple developer account. - Build and Run the project.
Assuming you have met the prerequisites above and are enrolled in biometrics, a new Secure Key will be created for you the first time you run the application. This private key resides in the Secure Enclave and is not, of course, associated with any blockchain account yet.
At this point, you have a couple of options:
- Add a new Authenticator (key) to the app using the "Add Additional Authenticators" button at the bottom of the Auths screen. (This should be a private key already on your EOSIO account.)
- Use the newly-generated Secure key. If you go this route, you will need to enable "Show Copy Public Key Option" in iOS Settings > Authenticator (see screenshot below), copy the key, and use another tool, such as Cleos, to add the key to your blockchain account.
If you are running the app in Simulator, ensure that you are "Enrolled" in Touch ID or Face ID. (Hardware
> Face ID
> Enrolled
) or (Hardware
> Touch ID
> Enrolled
). You will then be required to import a new private key if you haven't already done so on that particular Simulator instance.
When signing transactions on Simulator, you will be prompted for biometrics. Similar to enrolling above, when prompted, you will need to navigate to the same menu and select Matching Face
or Matching Touch
to approve.
If you want to start out by test driving the EOSIO Reference iOS Authenticator App for yourself, we recommend checking out our Tropical Example web app. Tropical Example is a mock web application for renting properties and provides instructions and a script for setting up a local chain bootstrapped with all of the necessary, compliant contracts for making the experience work.
Specifically, follow the instructions under the Running Tropical Example header. (Of course, we recommend reading the rest of the README there too, which will provide more context around how the pieces work together to provide the user with a secure and positive user experience.)
One important note to keep in mind: the web application and local blockchain will both be running on localhost
, so you will need to use the EOSIO Reference iOS Authenticator App in the Simulator running on the same machine for this particular example web app.
A Selective Disclosure Request is akin to a signature provider's getAvailableKeys()
call. In fact, in most cases, that's exactly what is happening under the hood.
- From an app that supports integration with the iOS Authenticator App, attempt to login or take some action that will kick off a transaction signing request.
- iOS may ask you if you want to open Authenticator. Choose "Open."
- iOS will switch you over to the EOSIO Reference iOS Authenticator App where you will be presented with the Selective Disclosure request. The information from this selective disclosure comes from the metadata associated with the application manifest. You can either Allow or Deny this request.
- If the request is allowed, the Reference iOS Authenticator App will return your public keys to the requesting application. In most cases, these will be cached for a period of time by the requesting application or until you log out. Subsequent
getAvailableKeys()
calls usually pull from this cache without triggering another Selective Disclosure request, unless the user has previously logged out of the requesting application.
- From an app that supports integration with the iOS Authenticator App, attempt to execute some action that requires a signature.
- The Reference iOS Authenticator App will open a view with the transaction request, including the Ricardian Contracts of the actions. You can either Approve or Cancel this request.
- If the user allows the request, they will be prompted for biometric confirmation.
- Assuming the user authenticates biometricly, the transaction will be signed with the keys from the Secure Enclave and/or Keychain.
- The transaction and signatures will be returned to the requesting app, which may, in turn, broadcast the transaction to the chain. (Most of the tooling broadcasts by default.)
The Reference Authenticator Apps follow the EOSIO Auth Transport Protocol specification defining inter-application transports and the payloads sent over those transports.
There is some configuration needed in the integrating app, and there are a few different ways to interact with the iOS Authenticator App from an integrating web or native app.
- Your app must conform to the Manifest Specification.
- Contracts for any action included in a transaction by your app must include a Ricardian contract conforming with the Ricardian Specification.
- Chains on which you wish to transact must have the
eosio.assert
contract deployed and a chain name and icon declared. - Apps must be served over HTTPS or locally from
localhost
.
Configure the EOSIO SDK for Swift EosioTransaction
with the Reference iOS Authenticator Signature Provider.
See the Basic Usage documentation in the EOSIO SDK for Swift repo for instructions on configuring EOSIO SDK for Swift with a signature provider.
Additionally, refer to Reference iOS Authenticator Signature Provider README for more information around using that signature provider to interact with the EOSIO Reference iOS Authenticator App.
Choose a solution for interacting with the Reference iOS Authenticator App:
- Use the Universal Authenticator Library and the UAL for EOSIO Reference Authenticator (easiest).
- UAL will detect that the app is running in Mobile Safari on iOS and will configure EOSJS with a signature provider facilitating communication between the web app and the Authenticator App.
- Read the documentation on the Tropical example app to learn how to use the UAL.
- Directly instantiate EOSJS with the EOSJS Signature Provider for EOSIO Authenticator in iOS.
- This class implements the EOSJS Signature Provider interface. The documentation describes how to utilize it directly with EOSJS.
- Directly use the iOS Deep Linking API.
- The integrating app will need to post requests and listen for responses following the EOSIO Auth Transport Protocols envelope formats:
- Requests: URL Query String Payload transport
- Responses: URL Hash Fragment Identifier transport
- The integrating app will need to post requests and listen for responses following the EOSIO Auth Transport Protocols envelope formats:
Under the hood, integrating apps interact with the EOSIO Reference iOS Authenticator App through the iOS Deep Link transport and the EOSIO Authentication Transport Protocol. However, that communication is generally abstracted away from app developers by the appropriate signature providers:
- EOSIO SDK for Swift: Reference iOS Authenticator Signature Provider for native iOS apps
- EOSJS Signature Provider for EOSIO Authenticator in iOS for web apps using EOSJS
Web applications using the Universal Authenticator Library will find it easiest to use the UAL for EOSIO Reference Authenticator, which allows web apps to work with both this app on iOS and its Chrome Extension counterpart.
Internally, the iOS Authenticator App uses EOSIO SDK for Swift along with the EOSIO SDK for Swift: Vault Signature Provider to get available keys from and sign with the device's Secure Enclave or the Keychain.
While the flowchart above emphasizes the request lifecycle, simply reverse the arrows and you have the response path. The transaction is signed in the Secure Enclave and/or Keychain, sent back to the Reference iOS Authenticator App via EOSIO SDK for Swift, and back through the iOS Deep Link Transport via the callback URL specified in the original request, eventually reaching all the way back to requesting app and user.
The EOSIO Reference iOS Authenticator App does not directly communicate with any EOSIO chains or nodes. It is entirely chain unaware and relatively chain agnostic. In fact, there is no way to configure networks or RPC endpoints in the iOS app because it doesn't need them.
This simplicity presents an interesting challenge, though. The Authenticator App must display to the user information about what they're signing and information about the blockchain they're signing the transaction for. But where does that information come from if not from the chain directly?
The answer is that all of the information presented to the user at the time of Selective Disclosure and Transaction Signing comes in with the payload from the requesting application. But that presents another problem: how can we trust that the requesting/integrating app isn't providing false information to the user about what they're signing or the chain on which they're signing?
For this, we employ the Manifest Specification and the Assert Contract.
The EOSIO Reference iOS Authenticator App adheres to the Manifest Specification. All checks described in the Manifest Specification are validated by the iOS app.
As part of the Manifest Specification, the EOSIO Reference iOS Authenticator App will append an invisible-to-the-user eosio.assert::require
action with the following parameters:
chain_params_hash
: Hash of the chain information from the Application Metadata for the chain defined in the request envelope.manifest_id
: Hash of the Manifest for the chain defined in the request envelope.actions
: An array of actions whitelisted in the Manifest.abi_hashes
: An array of the hashed ABIs included in the request envelope.
This action, with the above parameters, will be added to the transaction so that the chain can validate that these values match what is registered on chain. If any of these validations fails, the entire transaction will be rolled back and rejected.
This has another implication: block producers must deploy the eosio.assert
contract and declare a chain name and chain icon.
NOTE: The addition of this require
action can be overridden. But this must be done as part of the request from the requesting application and in the iOS Authenticator App with the addAssertToTransactions
security exclusion. See the Insecure Mode section for more information.
The EOSIO Reference iOS Authenticator App uses the platform-supplied Secure Enclave and Keychain to secure all private keys. Private keys stored in the Secure Enclave cannot even be known by the iOS Authenticator App itself.
The EOSIO Reference iOS Authenticator App has a developer settings page that allows application developers to enable Insecure Mode
in order to bypass various security measures for development purposes. Turning off security measures could lead to DISASTROUS results.
To enable Insecure Mode
follow the steps below for both the iOS Authenticator Appp and the application being developed.
- To enable
Insecure Mode
, tap on the settings cog icon in the upper right-hand corner. - Tap the "Developer Tools" entry.
- Toggle "Insecure Mode" on.
- Enter the application domain or subdomain in the input field and tap the "Add" button.
The integrating application must add the securityExclusions options to the Request Envelope as part of the EOSIO Transport Protocol.
If using the UAL for EOSIO Reference Authenticator, these can be passed in along with the authenticator options during UAL instantiation. The same applies when using the EOSJS Signature Provider for EOSIO Authenticator in iOS directly.
Interested in contributing? That's great! Here are some Contribution Guidelines and the Code of Conduct.
The following suggestions are beyond the scope of this limited thought leadership reference app. We encourage the community to contribute to this repo, or fork it and innovate!
- Apps facilitating onboarding of new Secure Enclave keys to users' accounts.
- Multi-device support and onboarding new devices: Could one device onboard another?
- If you lose your device(s), you lose your Secure Enclave keys. How can recovery be done without custodians?
- Support for Universal Links and other transports.
- Cross-platform signing. Could the EOSIO Reference Chrome Extension Authenticator App on desktop trigger a push to sign from this iOS app?
- Autosigning/whitelisted actions. Via Push Notification? In the background?
See LICENSE for copyright and license terms. Block.one makes its contribution on a voluntary basis as a member of the EOSIO community and is not responsible for ensuring the overall performance of the software or any related applications. We make no representation, warranty, guarantee or undertaking in respect of the software or any related documentation, whether expressed or implied, including but not limited to the warranties or merchantability, fitness for a particular purpose and noninfringement. In no event shall we be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or documentation or the use or other dealings in the software or documentation. Any test results or performance figures are indicative and will not reflect performance under all conditions. Any reference to any third party or third-party product, service or other resource is not an endorsement or recommendation by Block.one. We are not responsible, and disclaim any and all responsibility and liability, for your use of or reliance on any of these resources. Third-party resources may be updated, changed or terminated at any time, so the information here may be out of date or inaccurate.
Wallets and related components are complex software that require the highest levels of security. If incorrectly built or used, they may compromise users’ private keys and digital assets. Wallet applications and related components should undergo thorough security evaluations before being used. Only experienced developers should work with this software.