diff --git a/docs/Introduction.md b/docs/Introduction.md index ba97735..0b1bcc8 100644 --- a/docs/Introduction.md +++ b/docs/Introduction.md @@ -25,7 +25,11 @@ At a structural level, a Turnkey Organization is comprised of a few core resourc
- +
diff --git a/docs/Security/Quorum-deployment.md b/docs/Security/Quorum-deployment.md index 9aed595..138575c 100644 --- a/docs/Security/Quorum-deployment.md +++ b/docs/Security/Quorum-deployment.md @@ -11,8 +11,12 @@ Each instance of QOS is configured with a Quorum Set – A group of individuals After the service is launched, QOS responds to attestation requests and waits to receive key shares from QOS Operators or members of the Quorum Set. Once a threshold number of shares have been sent into the enclave it will reconstruct its core secret and launch the application it was provisioned with. This process is outlined in the images below: -- +
+
Remote attestation is the process by which core attributes of a machine can be retrieved and verified from a remote location. The enclave’s secure co-processor, in this case AWS’s NSM, observes the enclave as it is being launched and records certain important values such as the hash of the enclave image, the hash of the kernel, and the hash of the boot filesystem. This means that each attestation request verifies that the code actually running in the enclave is only the code we expect to be running. diff --git a/docs/Security/Secure-enclaves.md b/docs/Security/Secure-enclaves.md index 763662b..fc3b3cc 100644 --- a/docs/Security/Secure-enclaves.md +++ b/docs/Security/Secure-enclaves.md @@ -11,8 +11,12 @@ Secure enclaves, also called Trusted Execution Environments, are highly constrai The following outlines the structure of a single enclave application: -- +
+
In this diagram _Host_ represents a standard AWS virtual machine. We run a basic application that receives traffic from the network and calls into the enclave. This creates a layer of insulation from our most secure environment and offers a convenient place to gather metrics and other operational information about the enclaves. diff --git a/docs/Security/Verifiable-data.md b/docs/Security/Verifiable-data.md index b029a84..f140b13 100644 --- a/docs/Security/Verifiable-data.md +++ b/docs/Security/Verifiable-data.md @@ -12,5 +12,8 @@ By verifying the authenticity of data using cryptographic signatures (no passwor The entire Turnkey architecture including this verifiable data flow is described below:- +
\ No newline at end of file diff --git a/docs/getting-started/Examples.md b/docs/getting-started/Examples.md index 10270e1..6e9eaeb 100644 --- a/docs/getting-started/Examples.md +++ b/docs/getting-started/Examples.md @@ -54,7 +54,11 @@ A wallet application showing how users can register and authenticate using passk 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).- +
See https://wallet.tx.xyz (and https://github.com/tkhq/demo-passkey-wallet for the code). @@ -64,7 +68,11 @@ See https://wallet.tx.xyz (and https://github.com/tkhq/demo-passkey-wallet for t 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.- +
See https://github.com/tkhq/demo-ethers-passkeys for the code. @@ -74,7 +82,11 @@ See https://github.com/tkhq/demo-ethers-passkeys for the code. 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.- +
See https://github.com/tkhq/demo-viem-passkeys for the code. @@ -84,7 +96,11 @@ See https://github.com/tkhq/demo-viem-passkeys for the code. A simple example using Turnkey and Figment to easily automate ETH staking.- +
See https://docs.figment.io/recipes/stake-eth-from-turnkey for the code. \ No newline at end of file diff --git a/docs/getting-started/Quickstart.md b/docs/getting-started/Quickstart.md index 26130f9..5e69647 100644 --- a/docs/getting-started/Quickstart.md +++ b/docs/getting-started/Quickstart.md @@ -18,7 +18,11 @@ This quickstart will guide you through Turnkey’s onboarding, adding an API key All API requests require an organization ID. Yours can be located in the user dropdown menu at the top right corner of the dashboard. - + For convenience, it's worth setting this as a permanent shell variable: @@ -50,7 +54,11 @@ When you run this command, Turnkey’s CLI generates an API key pair and **store Navigate to your user page by clicking on "User Details" in the user dropdown menu. - + Click on "Create API keys" and follow the prompts to add the generated public API key. You'll be required to authenticate with the same authenticator used during onboarding. After this succeeds, you should be all set to interact with our API. diff --git a/docs/getting-started/email-recovery.md b/docs/getting-started/email-recovery.md index 9a68539..4a0802a 100644 --- a/docs/getting-started/email-recovery.md +++ b/docs/getting-started/email-recovery.md @@ -19,7 +19,11 @@ 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:- +
Initiating a new email recovery require proper permissions via policies or being a parent organization. See [Authorization](#authorization) for more details. @@ -35,7 +39,11 @@ 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.- +
diff --git a/docs/integration-guides/export-wallets.md b/docs/integration-guides/export-wallets.md index 96b881a..ff1c9c6 100644 --- a/docs/integration-guides/export-wallets.md +++ b/docs/integration-guides/export-wallets.md @@ -28,7 +28,11 @@ 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)):- +
Let's review these steps in detail: @@ -75,7 +79,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.- +
The exported wallet will remain stored within Turnkey’s infrastructure. In your Turnkey dashboard, the exported user Wallet will be flagged as “Exported”. @@ -113,7 +121,11 @@ It works by anchoring export in a **target encryption key** (TEK). This target e The following diagram summarizes the flow:- +
The public part of this key pair is passed as a parameter inside of a signed `EXPORT_WALLET` or `EXPORT_PRIVATE_KEY` activity. diff --git a/docs/passkeys/discoverable.md b/docs/passkeys/discoverable.md index 2db5ee9..4392142 100644 --- a/docs/passkeys/discoverable.md +++ b/docs/passkeys/discoverable.md @@ -23,8 +23,16 @@ 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:- - + +
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. diff --git a/docs/passkeys/integration.md b/docs/passkeys/integration.md index 74bc90a..9272f80 100644 --- a/docs/passkeys/integration.md +++ b/docs/passkeys/integration.md @@ -11,7 +11,11 @@ sidebar_position: 2 A typical passkey flow is composed of 4 main steps, depicted below:- +
1. Your app frontend triggers a passkey prompt. diff --git a/docs/passkeys/introduction.md b/docs/passkeys/introduction.md index 5e44807..e9664b1 100644 --- a/docs/passkeys/introduction.md +++ b/docs/passkeys/introduction.md @@ -47,8 +47,16 @@ 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:- - + +
Authentication to Turnkey requires a passkey signature. No password needed! diff --git a/docs/passkeys/options.md b/docs/passkeys/options.md index ca45905..80f0366 100644 --- a/docs/passkeys/options.md +++ b/docs/passkeys/options.md @@ -21,10 +21,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:- +
-- +
`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. @@ -58,9 +63,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:- +
- `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`. @@ -122,13 +127,20 @@ 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:- +
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:- +
### `attestation` diff --git a/docs/policy-management/Policy-overview.md b/docs/policy-management/Policy-overview.md index 14941bf..87c8c64 100644 --- a/docs/policy-management/Policy-overview.md +++ b/docs/policy-management/Policy-overview.md @@ -34,8 +34,12 @@ All policies defined within an Organization are evaluated on each request. The i Stated differently: -- +
+
Almost all actions on Turnkey are implicitly denied by default. There are a few exceptions, however: