better-auth-tempo
v0.1.0
Published
Tempo blockchain plugin for better-auth - passkey wallets, access keys, and WebAuthn integration
Maintainers
Readme
better-auth-tempo
Tempo blockchain plugin for better-auth. Enables passkey-based wallets, access key management, and WebAuthn authentication with Tempo address derivation.
Features
- Passkey Wallets: Each passkey automatically derives a Tempo blockchain address (P-256 → keccak256)
- Access Keys: Delegated signing authorization with token limits and expiry
- WebAuthn Integration: Full ceremony handling for passkey registration and authentication
- wagmi KeyManager: Drop-in integration with wagmi's WebAuthn connector
Installation
pnpm add better-auth-tempoServer Setup
import { betterAuth } from 'better-auth';
import { tempo } from 'better-auth-tempo';
export const auth = betterAuth({
// ... your config
plugins: [
tempo({
passkey: {
rpID: 'example.com',
rpName: 'My App',
origin: 'https://example.com',
},
// Static server wallet (shared across all users)
serverWallet: {
address: '0x...', // Backend signer for access keys
keyType: 'secp256k1',
},
// Or dynamic per-user server wallets:
// serverWallet: {
// getAddress: async ({ userId }) => {
// // Fetch from Turnkey, KMS, or your wallet infrastructure
// return getUserServerWallet(userId);
// },
// keyType: 'secp256k1',
// label: ({ userId }) => `Server wallet for ${userId}`,
// },
allowedChainIds: [42431], // Tempo Moderato testnet
}),
],
});Client Setup
import { createAuthClient } from 'better-auth/client';
import { tempoClient } from 'better-auth-tempo/client';
export const authClient = createAuthClient({
baseURL: 'http://localhost:3000',
plugins: [tempoClient()],
});Usage
Register a Passkey Wallet
const result = await authClient.registerPasskey({ name: 'My Wallet' });
if (result.data) {
console.log('Wallet address:', result.data.wallet.address);
}Authenticate with Passkey
const result = await authClient.authenticateWithPasskey();
if (result.data) {
console.log('Signed in as:', result.data.user.email);
}Create an Access Key
const { data, error } = await authClient.signKeyAuthorization({
config, // wagmi config
chainId: 42431,
keyType: 'secp256k1',
address: backendWalletAddress,
limits: [{ token: tokenAddress, amount: BigInt(1000) * BigInt(1_000_000) }],
});
if (data) {
await authClient.createAccessKey({
rootWalletId: myWallet.id,
keyWalletAddress: backendWalletAddress,
chainId: 42431,
authorizationSignature: data.signature,
authorizationHash: data.hash,
});
}wagmi KeyManager Integration
import { createTempoKeyManager } from 'better-auth-tempo/client';
import { webAuthn } from 'wagmi/connectors';
const keyManager = createTempoKeyManager(authClient);
const config = createConfig({
connectors: [
webAuthn({ keyManager }),
],
// ...
});API Reference
Server Plugin Options
| Option | Type | Description |
|--------|------|-------------|
| passkey.rpID | string | Relying Party ID (domain) |
| passkey.rpName | string | Human-readable app name |
| passkey.origin | string | Expected origin for WebAuthn |
| passkey.challengeMaxAge | number | Challenge TTL in seconds (default: 300) |
| serverWallet.address | 0x${string} | Backend wallet address |
| serverWallet.keyType | string | Key type: secp256k1, p256, webauthn |
| allowedChainIds | number[] | Allowed chain IDs for access keys |
| schema | object | Additional fields for tables |
Client Methods
| Method | Description |
|--------|-------------|
| registerPasskey() | Register passkey + create wallet |
| authenticateWithPasskey() | Sign in with passkey |
| listWallets() | List user's wallets |
| getServerWallet() | Get backend wallet for access keys |
| createAccessKey() | Create new access key |
| listAccessKeys() | List access keys (granted/received) |
| revokeAccessKey() | Revoke an access key |
| signKeyAuthorization() | Sign authorization with passkey |
License
MIT
