Skip to content

Commit

Permalink
docs: cleanup webauthn tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
sarahschwartz committed Sep 13, 2024
1 parent 72cf03e commit a0ccac3
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 30 deletions.
10 changes: 7 additions & 3 deletions content/tutorials/signing-transactions-with-webauthn/10.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ To break this down, the app will allow users to:

You can find the completed code inside the [Community Code repo](https://github.com/zkSync-Community-Hub/community-code/code/webauthn).

::callout{icon="i-heroicons-heart"}
Special thanks to the [Clave](https://github.com/getclave) team for helping with this example.
::

## Introduction to WebAuthn

WebAuthn, short for Web Authentication API, is an API built-in to your browser that allows your app to register and authenticate users.
Expand All @@ -44,9 +48,9 @@ including using biometric data (such as Apple's TouchID) or portable hardware de
There are two steps, or "ceremonies", for using WebAuthn: registration and authentication.

1. The first step, registration, is when the user creates a new key pair specific to the application they are using.
2. The second step, authentication, is used to send a challenge for WebAuthn to sign, and receive a signature in return.
2. The second step, authentication, is used to send a challenge to WebAuthn to sign using that key pair, and receive a signature in return.

In the frontend section, you will see in detail what these ceremonies look like.
In the frontend section, you will see in more detail what these ceremonies look like.

### Signatures

Expand All @@ -56,4 +60,4 @@ WebAuthn uses the secp256r1 elliptic curve for signing, while standard accounts
Without a helper function to handle verifying secp256r1 signatures, it can be really difficult to integrate a smart account with WebAuthn.
Luckily, we can utilize the `P256Verify` precompile to verify that a given WebAuthn signature matches a known public key.

In the next section, we will create the contracts for the demo app.
In the next section, we will create the contracts for the app.
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,25 @@ We can start by creating the contracts for the smart account, paymaster, and NFT
zksync-cli create contracts --template hardhat_solidity --project contracts
```

Enter the private key for a pre-configured rich wallet:
The CLI will prompt you to enter a private key for deploying.
Enter the private key below for a pre-configured rich wallet:

```shell
? Private key of the wallet responsible for deploying contracts (optional)
0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110
```

Once that is done, move into the `contracts` folders and delete the template contracts, scripts, and tests:
Once that is done, move into the `contracts` folders and
install the dependency below:

```shell
cd contracts
npm install -D @matterlabs/[email protected]
```

Then, delete the template contracts, scripts, and tests:

```shell
rm -rf ./contracts/*
rm -rf ./deploy/*
rm -rf ./test/*
Expand Down Expand Up @@ -68,7 +76,7 @@ This is a basic paymaster contract that allows us to sponsor transactions for us

### NFT Contract

Create a file in the `contracts/contracts` folder called `MyNFT.sol`.
Create another file in the `contracts/contracts` folder called `MyNFT.sol`.

```shell
touch contracts/MyNFT.sol
Expand Down Expand Up @@ -129,17 +137,15 @@ The smart account contract is where we perform the WebAuthn signature validation

### Understanding WebAuthn Signature Validation

The smart contract account implements a way to validate signatures created with WebAuthn.

The `_validateTransaction` function first checks to see if there is a valid secp256k1 signature from the account owner,
In the `Account.sol` contract, the `_validateTransaction` function checks to see if there is a valid secp256k1 signature from the account owner,
just like the example in the [Native AA Multisig](https://code.zksync.io/tutorials/native-aa-multisig) tutorial.
If the transaction is not signed by the standard account owner, the next check is to see if the transaction contains a valid WebAuthn signature.

```solidity [contracts/Account.sol]
:code-import{filePath="webauthn/contracts/contracts/Account.sol:_validateTransaction"}
```

The contract contains a state variable `r1Owner` to store the public key of the WebAuthn account that the owner wants to use.
The contract contains a state variable `r1Owner` to store the public key of the WebAuthn account that the owner wants to authorize.
The `updateR1Owner` function can update the value of the `r1Owner`.

```solidity [contracts/Account.sol]
Expand All @@ -150,14 +156,16 @@ The `updateR1Owner` function can update the value of the `r1Owner`.
:code-import{filePath="webauthn/contracts/contracts/Account.sol:updateR1Owner"}
```

To validate the signature, the `_validateWebAuthnSignature` first extracts the `authenticatorData`, `clientData`, and `rs` values from the decoded signature.
To validate the signature, the `_validateWebAuthnSignature` function
first extracts the `authenticatorData`, `clientData`, and `rs` values from the decoded signature.

It's important to note that the WebAuthn authentication process doesn't just sign the transaction data we send as a challenge.
The WebAuthn authentication process returns three pieces of information that we need for the validation process:
the WebAuthn signature, the `authenticatorData`, and the `clientData`.

The `extractChallengeFromClientData` extracts the WebAuthn challenge from the `clientData`, and checks to see if it matches the transaction hash.
This means that the exact transaction data that is submitted to the contract matches the transaction data signed by the WebAuthn account.
The `extractChallengeFromClientData` function extracts the WebAuthn challenge from the `clientData`, and checks to see if it matches the transaction hash.
If the values are equal,
this means that the exact transaction data that is submitted to the contract matches the transaction data signed by the WebAuthn account.

Next, the `_validateWebAuthnSignature` function checks for the malleability of the signature,
and checks to see if the WebAuthn user flags are set.
Expand Down Expand Up @@ -189,18 +197,18 @@ Open a new terminal and start a local in-memory node with `era_test_node`:
era_test_node run
```

Next, modify the `defaultNetwork` in the `hardhat.config.ts` file to deploy to the local in-memory node, and change the version of Solidity to `0.8.20`:
Next, replace your `hardhat.config.ts` file with the file below:

```ts
defaultNetwork: "inMemoryNode",
```
::drop-panel
::panel{label="hardhat.config.ts"}

```ts
solidity: {
version: "0.8.20",
},
```solidity [hardhat.config.ts]
:code-import{filePath="webauthn/contracts/hardhat.config.ts"}
```

::
::

### Adding the Deploy Script

Create a new file inside the `deploy` folder called `deploy.ts`:
Expand All @@ -209,11 +217,7 @@ Create a new file inside the `deploy` folder called `deploy.ts`:
touch deploy/deploy.ts
```

Copy and paste the code below. This script will:

- deploy the `AAFactory` contract
- deploy the NFT contract and mint an NFT
- deploy the paymaster contract and send funds to it from the preconfigured rich account.
Copy and paste the code below.

::drop-panel
::panel{label="deploy.ts"}
Expand All @@ -225,6 +229,12 @@ Copy and paste the code below. This script will:
::
::

This script will:

- deploy the `AAFactory` contract
- deploy the NFT contract and mint an NFT
- deploy the paymaster contract and send funds to it from the pre-configured rich account.

### Running the Deploy Script

Finally, compile and deploy the contracts with:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: Build the frontend for the WebAuthn app.

We will use Next.js to build the frontend.

Move out of your `contract` folder and into the `zksync-webauthn` folder.
Move out of your `contract` folder and back into the `zksync-webauthn` folder.
Make a new Next.js project for the frontend using the configuration below:

```shell
Expand Down Expand Up @@ -75,7 +75,7 @@ Copy the `Layout` component below to your file:
### Styles
Let's also update the styles in `globals.css`.
Let's also update the styles in `src/styles/globals.css`.
::drop-panel
::panel{label="globals.css"}
Expand Down Expand Up @@ -191,6 +191,10 @@ touch utils/tx.ts
::
::
::callout{icon="i-heroicons-exclamation-circle"}
Note: you may need to update the import at the top from `zksync-ethers/build/utils` to `zksync-ethers/build/src/utils`.
::
This file contains helper functions to get data for a transaction
and register a new passkey in a smart account.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ touch src/pages/create-account.tsx
::
This page is where users can deploy a new instance of a smart account using the `AAFactory` contract.
The wallet used to create the acccount is saved temporaily saved in the application using the `useSetWallet` hook,
The wallet used to create the acccount is temporaily saved in the application using the `useSetWallet` hook,
and the deployed smart contract account address is saved to the browser's local storage with the `useSetAccount` hook.
For testing purposes, when a new account is created, some test funds are sent to the account from a pre-configured rich wallet.
Expand Down Expand Up @@ -206,6 +206,6 @@ Follow the order of the buttons on the home page:
1. Start by creating a new account.
1. Next, register a new passkey.
1. Finally, you can use the registered passkey to transfer ETH and mint an NFT!
1. Finally, you can use the registered passkey to transfer ETH and mint an NFT.
Note: You can edit or remove your browser passkeys by going to `chrome://settings/passkeys`.

0 comments on commit a0ccac3

Please sign in to comment.