Awesome
EOSIO WebAuthn Example Web App
Overview
WebAuthn is a Web Authentication API standard recently finalized by W3C and supported, to varying degrees, by the Chrome, Firefox, and Edge web browsers and some mobile platforms. The standard enables passwordless primary and multi-factor user authentication flows using authenticators such as security keys (e.g., YubiKey) or built-in platform authenticators (e.g., biometrics).
EOSIO is the first blockchain protocol we are aware of to adopt the WebAuthn standard.
More information about WebAuthn can be found at https://webauthn.guide.
This example app demonstrates how an application running on a private chain could:
- generate WebAuthn-compatible keys for users
- request signatures from users with those keys
This is facilitated by eosjs
, a WebAuthn Signature Provider for eosjs
, and the built-in browser Web Authentication API. The browser prompts the user to authenticate with their security key or built-in platform authenticator.
About EOSIO Labs™
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.
Contents
- Limitations
- Building and Running The App
- Building and Running the Server
- Create Test Chain With WebAuthn Support
- Contributing
- License & Legal
Limitations
- Server only supports a single client (browser tab) connecting to it
- Server only supports a single user; it assumes all stored keys belong to that user
- Server only supports a single hardware key; it assumes all stored keys came from that key
- Touch ID on Mac is not currently supported
createKey
inClientRoot.tsx
- assumes it's served from localhost; other domains will break
- hard codes the
user
field - hard codes the
challenge
field; this should be randomly generated by the server then checked by the server
- If
keys.json
(maintained by the server) is lost, then the keypairs become inaccessible. It's important to note that WebAuthn doesn't provide a way to recover from this. - ⚠️ There is currently no way to display Ricardian contracts to users when using WebAuthn. For this reason, WebAuthn, when used in conjunction with EOSIO, should be used with caution and only on private chains and applications already trusted by the end user. ⚠️
Building and Running The App
Running this app will create an HTTP server listening on 0.0.0.0:8000
meaning it would typically be accessible via http://localhost:8000
(and from non-localhost as well). However, WebAuthn requires usage from an HTTPS origin. You will need to place an HTTPS proxy in front of the server and modify server source code with the resulting domain name and port.
Running Locally With nodeos Docker Image
Prerequisites
- Install Docker
- Install Docker Compose (included with Docker for Desktop on Mac)
- Install HAProxy
- On Mac:
brew install haproxy
- On Ubuntu:
apt-get install haproxy=1.8.\*
- On Mac:
- Install nodejs
Setup
The following command will generate the required SSL certificate, perform the required yarn install/setup, and execute all necessary actions against the chain.
yarn setup
Starting/Stopping
To start the chain, haproxy, and the app:
yarn start
To stop all of the above, CTRL+C the app and then:
yarn stop
Cleaning the chain
To reset the chain:
yarn clean
Running any arbitrary cleos command
yarn cleos <parameters to cleos>
If the wallet locks,
yarn unlock-wallet
Running Locally With nodeos Built From Source
Prerequisites
- Install HAProxy
- Install nodejs
HTTPS proxy via self-signed localhost certificate:
The following describes one way of placing an HTTPS proxy in front of the server via the program haproxy
along with a self-signed certificate that you instruct your browser to trust.
Create a certificate and private key:
$ openssl req \
-x509 \
-nodes \
-new \
-newkey rsa:4096 \
-keyout localhostca.key \
-out localhostca.crt \
-sha256 \
-days 3650 \
-config <(cat <<EOF
[ req ]
prompt = no
distinguished_name = subject
x509_extensions = x509_ext
[ subject ]
commonName = localhost
[ x509_ext ]
subjectAltName = @alternate_names
basicConstraints=CA:TRUE,pathlen:0
[ alternate_names ]
DNS.1 = localhost
EOF
)
Combine the .cert file and the .key into a .pem file:
$ cat localhostca.crt localhostca.key > localhostca.pem
Make a haproxy.cfg file which will listen on HTTPS port 7000 and forward to port 8000:
defaults
timeout connect 10000ms
timeout client 50000ms
timeout server 50000ms
frontend https-in
bind *:7000 ssl crt localhostca.pem
use_backend http_backend
backend http_backend
server server1 127.0.0.1:8000
Run the program haproxy:
$ haproxy -f haproxy.cfg
You will need to add the localhostca.crt
certificate file as a trusted certificate in your browser. The steps to accomplish this vary based on operating system and browser.
Note that it would be good practice to remove this certificate from being trusted at the conclusion of your development.
Modification of server origin in source:
The server domain name and port must be specified in the source of this application. Modify the socketUrl
in src/client/ClientRoot.tsx
to be the valid HTTPS url to the HTTPS proxy. If you performed the self-signed & haproxy instructions above you would change this to https://localhost:7000
Building and Running the Server
$ git submodule update --init --recursive
$ yarn
$ rm -rf node_modules/eosjs && bash -c "cd external/eosjs && yarn" && yarn add file:external/eosjs
$ rm -rf dist && yarn server
The server is now running and you can now access it via the HTTPS proxy you just created.
Create Test Chain With WebAuthn Support
This starts a minimal test chain with some upgrades activated. This guide assumes you're already familiar with creating and using test chains.
Note: If using the Docker setup, only the account creation and token transfers must be done.
All other steps are handled in the setup
script.
Prerequisites:
- Install
EOSIO/eos
branchwebauthn
- Install
EOSIO/eosio.cdt
branchv1.6.x
- Use
EOSIO/eosio.cdt
to buildEOSIO/eosio.contracts
branchv1.7.0-rc1
Create a wallet, or unlock existing:
Use $ cleos wallet create
or $ cleos wallet unlock
Add the default key:
$ cleos wallet import --private-key 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
Create a test chain:
This will create a fresh chain in directory my-chain
. chain_api_plugin
and producer_api_plugin
enable the commands which follow.
$ mkdir my-chain
$ cd my-chain
$ nodeos --data-dir ./data --config-dir ./config --plugin eosio::chain_api_plugin --plugin eosio::producer_api_plugin --http-validate-host 0 --access-control-allow-origin "*" -p eosio -e 2>stderr &
Preactivate feature:
Do this before installing eosio.bios:
$ curl -X POST http://127.0.0.1:8888/v1/producer/schedule_protocol_feature_activations -d '{"protocol_features_to_activate": ["0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd"]}' | jq
Install contracts, activate WebAuthn keys, and create tokens:
$ cleos create account eosio eosio.token EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
$ cleos set contract eosio <path-to-eosio.contracts>/build/contracts/eosio.bios -p eosio
$ cleos set contract eosio.token <path-to-eosio.contracts>/build/contracts/eosio.token -p eosio.token
$ cleos push action eosio activate '["4fca8bd82bbd181e714e283f83e1b45d95ca5af40fb89ad3977b653c448f78c2"]' -p eosio
$ cleos push action eosio.token create '["eosio","10000000.0000 SYS"]' -p eosio.token
$ cleos push action eosio.token issue '["eosio","10000000.0000 SYS",""]' -p eosio
Use app to generate 2 keys. Use them below:
$ cleos create account eosio usera <a-generated-public-key>
$ cleos create account eosio userb <a-generated-public-key>
$ cleos create account eosio userc <a-generated-public-key>
$ cleos create account eosio userd <a-generated-public-key>
$ cleos transfer eosio usera "1000.0000 SYS" ""
$ cleos transfer eosio userb "1000.0000 SYS" ""
$ cleos transfer eosio userc "1000.0000 SYS" ""
$ cleos transfer eosio userd "1000.0000 SYS" ""
Contributing
License
Important
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 of 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. Any person using or offering this software in connection with providing software, goods or services to third parties shall advise such third parties of these license terms, disclaimers and exclusions of liability. Block.one, EOSIO, EOSIO Labs, EOS, the heptahedron and associated logos are trademarks of Block.one.
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.