Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions src/pages/guide/use-accounts/authorize-access-keys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ import { Tabs, Tab } from 'vocs'

Send stablecoin payments using an access key: a secondary signing key that lets you transact without repeated passkey prompts. Access keys can be scoped with spending limits and expiry for security.

:::info[Coming with T5]
After the [T5 network upgrade](/protocol/upgrades/t5), `key_authorization` gains an optional `witness: bytes32` field ([TIP-1053](https://github.com/tempoxyz/tempo/blob/main/tips/tip-1053.md)). "Sign-In with Tempo" style apps can derive a 32-byte witness from their challenge and include it in the access-key authorization, so a single user signature both authorizes the access key and binds to the app's challenge — replacing the current two-prompt flow. No breaking change; existing flows continue to work unchanged.
:::

## Demo

By the end of this guide you will be able to send payments on Tempo using an access key. Notice that no passkey prompt appears when sending a payment.
Expand All @@ -29,6 +25,37 @@ By the end of this guide you will be able to send payments on Tempo using an acc
<SendPayment stepNumber={3} last />
</Demo.Container>

To turn this into a login flow, ask your server for a single-use challenge before connect, derive a 32-byte `witness`, and include it in the same access-key authorization. The user approves one passkey prompt, and the signed authorization can be verified by your server before the app uses the access key.

```ts twoslash [login.ts]
// @noErrors
import { keccak256, parseUnits, stringToBytes } from 'viem'
import { Expiry } from 'accounts'

const challenge = await fetch('/api/login/challenge').then((res) => res.text())

const witness = keccak256(
stringToBytes(`tempo-login:${window.location.origin}:${challenge}`),
)

const authorizeAccessKey = {
expiry: Expiry.days(7),
limits: [{
token: '0x20c0000000000000000000000000000000000001',
limit: parseUnits('100', 6), // 100 AlphaUSD
}],
scopes: [{
target: '0x20c0000000000000000000000000000000000001',
selector: 'transfer(address,uint256)',
}],
witness,
}
```

If you are signing the authorization directly with Viem, pass the same `witness` to `accessKey.authorize` or `accessKey.signAuthorization`.

Your server should verify that the returned key authorization was signed by the expected account, contains the expected `witness`, and matches the expiry, limits, and scopes your app requested. The protocol treats `witness` as opaque `bytes32`, so include your app origin or domain in the witness preimage and make the underlying challenge single-use.

## Steps

::::steps
Expand Down
Loading