Skip to content

Commit

Permalink
typos. center images. resize export wallet images
Browse files Browse the repository at this point in the history
  • Loading branch information
Olivia Thet committed Nov 28, 2023
1 parent 0760932 commit 46eee23
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 26 deletions.
25 changes: 18 additions & 7 deletions docs/getting-started/Examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ That said, we have built out several example services and applications to help i
| [`demo-ethers-passkeys`](https://github.com/tkhq/demo-ethers-passkeys) | A NextJS app that demonstrates how to use `@turnkey/ethers` to build a passkey-powered application |
| [`demo-viem-passkeys`](https://github.com/tkhq/demo-viem-passkeys) | A NextJS app that demonstrates how to use `@turnkey/viem` to build a passkey-powered application |
| [`deployer`](https://github.com/tkhq/sdk/tree/main/examples/deployer/) | Compile and deploy a smart contract |
| [`email-recovery`](https://github.com/tkhq/sdk/tree/main/examples/email-recovery/) | A NextJS app that demonstrates how to use `@turnkey/iframe-stamper` to perform email |
| [`rebalancer`](https://github.com/tkhq/sdk/tree/main/examples/rebalancer/) | A demo application which showcases an example of how to use Turnkey for managing multiple types of keys & users |
| [`sweeper`](https://github.com/tkhq/sdk/tree/main/examples/sweeper/) | Sweep funds from one address to a different address |
| [`trading-runner`](https://github.com/tkhq/sdk/tree/main/examples/trading-runner/) | A sample application demonstrating a trading operation, using various private keys, users, and policies, powered by Uniswap |
Expand All @@ -39,9 +40,11 @@ That said, we have built out several example services and applications to help i

A minimal consumer wallet app powered by Turnkey. Behind the scenes, it uses [`@turnkey/ethers`](https://www.npmjs.com/package/@turnkey/ethers) for signing and WalletConnect (v1) for accessing dapps.

<video controls width="800px">
<source src="https://github.com/tkhq/demo-consumer-wallet/assets/127255904/2c3409df-2d7c-4ec3-9aa8-e2944a0b0e0a"/>
</video>
<p style={{ textAlign: "center" }}>
<video controls width="800px">
<source src="https://github.com/tkhq/demo-consumer-wallet/assets/127255904/2c3409df-2d7c-4ec3-9aa8-e2944a0b0e0a"/>
</video>
</p>

See https://github.com/tkhq/demo-consumer-wallet for the code.

Expand All @@ -50,30 +53,38 @@ See https://github.com/tkhq/demo-consumer-wallet for the code.
A wallet application showing how users can register and authenticate using passkeys.
This demo uses the Turnkey API to create a new [Turnkey Sub-Organization](./Sub-Organizations.md) for each user, create a testnet Ethereum address and send a transaction on Sepolia (ETH testnet).

<img src="/demo-passkey-wallet.png" alt="homepage screenshot" width="800px"/>
<p style={{ textAlign: "center" }}>
<img src="/demo-passkey-wallet.png" alt="demo passkey wallet screenshot" width="800px"/>
</p>

See https://wallet.tx.xyz (and https://github.com/tkhq/demo-passkey-wallet for the code).

### Demo Ethers Passkeys ([code](https://github.com/tkhq/demo-ethers-passkeys))

A simple application demonstrating how to create sub-organizations, create private keys, and sign with the [`@turnkey/ethers`](https://github.com/tkhq/sdk/tree/main/packages/ethers) signer, using passkeys.

<img src="/ethers-ui-screenshot.png" alt="homepage screenshot" width="800px"/>
<p style={{ textAlign: "center" }}>
<img src="/ethers-ui-screenshot.png" alt="ethers ui screenshot" width="800px"/>
</p>

See https://github.com/tkhq/demo-ethers-passkeys for the code.

### Demo Viem Passkeys ([code](https://github.com/tkhq/demo-viem-passkeys))

A similar, simple application demonstrating how to create sub-organizations, create private keys, and sign with the [`@turnkey/viem`](https://github.com/tkhq/sdk/tree/main/packages/viem) signer, using passkeys.

<img src="/viem-ui-screenshot.png" alt="homepage screenshot" width="800px"/>
<p style={{ textAlign: "center" }}>
<img src="/viem-ui-screenshot.png" alt="viem ui screenshot" width="800px"/>
</p>

See https://github.com/tkhq/demo-viem-passkeys for the code.

### Automated ETH staking ([code](https://docs.figment.io/recipes/stake-eth-from-turnkey))

A simple example using Turnkey and Figment to easily automate ETH staking.

<img src="/img/staking_example.png" alt="turnkey figment integration" width="700px"/>
<p style={{ textAlign: "center" }}>
<img src="/img/staking_example.png" alt="turnkey figment integration" width="700px"/>
</p>

See https://docs.figment.io/recipes/stake-eth-from-turnkey for the code.
10 changes: 7 additions & 3 deletions docs/getting-started/email-recovery.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ Email recovery starts with a new activity posted to Turnkey. This activity has t

This activity generates a new temporary API key pair (a "recovery credential"), saves the public key in organization data under the target user, and sends an email with the encrypted recovery credential:

<img src="/img/recovery_email.png" width="420" />
<p style={{ textAlign: "center" }}>
<img src="/img/recovery_email.png" alt="recovery email" width="420" />
</p>

Initiating a new email recovery require proper permissions via policies or being a parent organization. See [Authorization](#authorization) for more details.

Expand All @@ -33,7 +35,7 @@ Authorization for email recovery is based on our usual activity authorization: o
* `ACTIVITY_TYPE_RECOVER_USER` should be signed by the recovery credential sent via email. Even if not explicitly allowed by policy, a user is always able to add credentials to their own user. This includes adding a new authenticator when authenticated with a recovery credential. In other words, no special policy is needed to make this work: users are able to recover out-of-the-box.

<p style={{textAlign: 'center'}}>
<img src="/img/diagrams/email_recovery_authorization.png" width="500" height="200"/>
<img src="/img/diagrams/email_recovery_authorization.png" alt="email recovery authorization" width="500" height="200"/>
</p>


Expand Down Expand Up @@ -63,7 +65,9 @@ If you _never_ want to have email recovery enabled, our `CREATE_SUB_ORGANIZATION

Unlike typical email recovery functionality, Turnkey's email recovery doesn't send unencrypted tokens via emails. This ensures no man-in-the-middle attack can happen: even if the content of the recovery email is leaked, an attacker wouldn't be able to decrypt the recovery credential. The following diagram summarizes the flow:

<img src="/img/email_recovery_cryptography.png" />
<p style={{ textAlign: "center" }}>
<img src="/img/email_recovery_cryptography.png" alt="email recovery cryptography" />
</p>

Our email recovery flow works by anchoring recovery in a **target encryption key** (TEK). This target encryption key is a standard P-256 key pair and can be created in many ways: completely offline, or online inside of script using the web crypto APIs.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ In the rest of this guide we'll assume you are using these helpers.

Here's a diagram summarizing the email recovery flow step-by-step ([direct link](/img/email_recovery_steps.png)):

<img src="/img/email_recovery_steps.png" />
<p style={{ textAlign: "center" }}>
<img src="/img/email_recovery_steps.png" alt="email recovery steps" />
</p>

Let's review these steps in detail:

Expand Down
16 changes: 11 additions & 5 deletions docs/integration-guides/export-wallets.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ slug: /integration-guides/export-wallets
---
# Export Wallet

Turnkey's export functionality allows your end users to backup or transer a [Wallet](../getting-started/Wallets.md) by securely viewing the wallet's [mnemonic phrase](https://learnmeabitcoin.com/technical/mnemonic). We engineered this feature to ensure that the user can export their mnemonic without exposing the mnemonic itsef to Turnkey or your application.
Turnkey's export functionality allows your end users to backup or transfer a [Wallet](../getting-started/Wallets.md) by securely viewing the wallet's [mnemonic phrase](https://learnmeabitcoin.com/technical/mnemonic). We engineered this feature to ensure that the user can export their mnemonic without exposing the mnemonic itself to Turnkey or your application.

Follow along with the guide below to set up Wallet Export for your end users.

Expand All @@ -27,7 +27,9 @@ In the rest of this guide we'll assume you are using these helpers.

Here's a diagram summarizing the wallet export flow step-by-step ([direct link](/img/wallet_export_steps.png)):

<img src="/img/wallet_export_steps.png" />
<p style={{ textAlign: "center" }}>
<img src="/img/wallet_export_steps.png" alt="wallet export steps" height="200" />
</p>

Let's review these steps in detail:

Expand Down Expand Up @@ -72,9 +74,11 @@ Let's review these steps in detail:

Export is complete! The iframe now displays a numbered 3-column grid of words that form the mnemonic, directly to your end user.

<img src="/img/wallet_export_mnemonic.png" />
<p style={{ textAlign: "center" }}>
<img src="/img/wallet_export_mnemonic.png" alt="wallet mnemonic" height="280" />
</p>

The exported wallet will remain stored within Turnkey’s infrastructure. In your dashboard, the exported user Wallet will be flagged as “Exported”.
The exported wallet will remain stored within Turnkey’s infrastructure. In your Turnkey dashboard, the exported user Wallet will be flagged as “Exported”.

## UI customization

Expand Down Expand Up @@ -108,7 +112,9 @@ It works by anchoring export in a **target encryption key** (TEK). This target e

The following diagram summarizes the flow:

<img src="/img/wallet_export_cryptography.png" />
<p style={{ textAlign: "center" }}>
<img src="/img/wallet_export_cryptography.png" alt="export cryptography" height="320" />
</p>

The public part of this key pair is passed as a parameter inside of a signed `EXPORT_WALLET` or `EXPORT_PRIVATE_KEY` activity.

Expand Down
6 changes: 4 additions & 2 deletions docs/passkeys/discoverable.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ With terminology out of the way, what is a "discoverable" credential compared to

A discoverable credential is a self-contained key pair, stored on the end-user's device. Discoverable credentials are preferred because keys are self-contained, can easily be synced and can be used across devices independently. Crucially for UX, the end-user is able to list their passkeys and choose which device/passkey they'd like to use:

<img src="/img/passkeys/discoverable_device_choice.png" alt="Device selection on Chrome" width="400px" />
<img src="/img/passkeys/discoverable_passkey_choice.png" alt="Passkey selection on Chrome" width="321px" style={{marginLeft: '10px'}} />
<p style={{ textAlign: "center" }}>
<img src="/img/passkeys/discoverable_device_choice.png" alt="device selection on Chrome" width="400px" />
<img src="/img/passkeys/discoverable_passkey_choice.png" alt="passkey selection on Chrome" width="321px" style={{marginLeft: '10px'}} />
</p>

With discoverable credentials you don't have to keep track of credential IDs. Your authentication flow can simply be: "prompt the user with passkey authentication", and let the browser or device native UX handle the rest! The downside is you lose some control over these prompts, because they will vary depending on your users' OS and browser.

Expand Down
4 changes: 3 additions & 1 deletion docs/passkeys/integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ sidebar_position: 2

A typical passkey flow is composed of 4 main steps, depicted below:

<img src="/img/passkeys/turnkey_passkey_flow.png" alt="Passkey prompt on Turnkey" width="920px" />
<p style={{ textAlign: "center" }}>
<img src="/img/passkeys/turnkey_passkey_flow.png" alt="passkey prompt on Turnkey" width="920px" />
</p>

1. Your app frontend triggers a passkey prompt.
2. Your end-user uses their device to produce a signature with their passkey, and a signed request is produced.
Expand Down
6 changes: 4 additions & 2 deletions docs/passkeys/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ Support also varies by operating system: [this matrix](https://passkeys.dev/devi

We believe **it's time to move away from passwords** so we've built Turnkey without them. When you authenticate to Turnkey you'll be prompted to create a new passkey:

<img src="/img/passkeys/turnkey_authenticator_selection.png" alt="Authenticator selection on Turnkey" width="400px" />
<img src="/img/passkeys/turnkey_passkey_prompt.png" alt="Passkey prompt on Turnkey" width="420px" />
<p style={{ textAlign: "center" }}>
<img src="/img/passkeys/turnkey_authenticator_selection.png" alt="Authenticator selection on Turnkey" width="400px" />
<img src="/img/passkeys/turnkey_passkey_prompt.png" alt="Passkey prompt on Turnkey" width="420px" style={{marginLeft: '10px'}} />
</p>

Authentication to Turnkey requires a passkey signature. No password needed!

Expand Down
22 changes: 17 additions & 5 deletions docs/passkeys/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ This is the challenge signed by the end-user for registration. During registrati

Number of seconds before "giving up". The browser will simply show a timeout popup:

<img src="/img/passkeys/timeout.png" alt="authenticatorAttachment unspecified" width="360px"/><br/><br/>
<p style={{ textAlign: "center" }}>
<img src="/img/passkeys/timeout.png" alt="authenticatorAttachment unspecified" width="360px"/>
</p>
<br/>
<br/>

This UI isn't very helpful, so we recommend making the timeout long (5 minutes). The less your users see this, the better.

Expand All @@ -32,7 +36,9 @@ The `rp` options is an object with 2 fields: `id` and `name`.

`rp.id` will show up in the initial registration popup:

<img src="/img/passkeys/registration_options_rpid.png" alt="RPID in registration prompt" width="360px"/>
<p style={{ textAlign: "center" }}>
<img src="/img/passkeys/registration_options_rpid.png" alt="RPID in registration prompt" width="360px"/>
</p>

`rp.name` doesn't show up in the popup so can be set to anything. We recommend setting it to the correctly capitalized name of your app, in case browsers start showing it in their native UIs in the future.

Expand All @@ -53,7 +59,9 @@ Turnkey currently supports P256 only. In the near future Turnkey will support RS
The `user` field has three sub-fields:
- `id`: also known as "user handle", isn't visible to the end-user. We **strongly recommend setting this to a random value** (e.g. `const id = new Uint8Array(32); crypto.getRandomValues(id)`) to make sure a new passkey is created. Be aware: **if you accidentally set this value to an existing user handle, the corresponding passkey will be overridden!**. [This section of spec](https://www.w3.org/TR/webauthn-2/#dictionary-user-credential-params) is clear on the matter: "the user handle ought not be a constant value across different accounts, even for non-discoverable credentials".
- `name`: this will show up in the passkey list modal (see screenshot below). We recommend setting this to something the user will recognize: their email, the name of your app, or potentially leave this up to the user:<br/>
<img src="/img/passkeys/user_name_and_display.png" alt="RPID in registration prompt" width="360px"/>
<p style={{ textAlign: "center" }}>
<img src="/img/passkeys/user_name_and_display.png" alt="RPID in registration prompt" width="360px"/>
</p>
- `displayName`: as far as we can tell this doesn't show up in current browser UIs. It might show up in future iterations so it's best to populate this with the same value as `name`.

### `authenticatorSelection`
Expand Down Expand Up @@ -113,11 +121,15 @@ The credential ID needs to be passed as a buffer but is returned from registrati

If the wrong credential ID is specified, `transports: ["internal"]` is set, browsers error right away because they can enumerate internal credentials. Chrome, for example, displays the following error:

<img src="/img/passkeys/no_passkey_available.png" alt="Chrome error when no matching passkey has been found for the provided Credential ID" width="360px"/>
<p style={{ textAlign: "center" }}>
<img src="/img/passkeys/no_passkey_available.png" alt="Chrome error when no matching passkey has been found for the provided Credential ID" width="360px"/>
</p>

However, if the wrong credential ID is specified without `transports` set (or with other-than-internal `transports` set), browsers won't error right away because they can't enumerate external credentials. They will display an error once the user has pressed their security key or gone through the cross-device passkey flow:

<img src="/img/passkeys/wrong_credential_id.png" alt="Chrome error when the credential ID used by the user is not in the allowCredentials list" width="360px"/>
<p style={{ textAlign: "center" }}>
<img src="/img/passkeys/wrong_credential_id.png" alt="Chrome error when the credential ID used by the user is not in the allowCredentials list" width="360px"/>
</p>

### `attestation`

Expand Down

0 comments on commit 46eee23

Please sign in to comment.