Appearance
Signing requests with an authorization key
If you have an authorization key enabled in the Dashboard, all requests to take actions from user's wallets must be signed with this key. This helps ensure that only actions that explicitly authorized by your server are executed with delegated wallets.
Follow the guide below to ensure that requests to user's wallets are appropriately signed, whether you integrate the SDK or the REST API directly.
Using @privy-io/server-auth
To sign requests with Privy's Server SDK, when initializing your instance of the PrivyClient
, pass your authorization private key from the dashboard to the client's constructor like so:
tsx
import { PrivyClient } from '@privy-io/server-auth';
...
const privy = new PrivyClient('insert-your-app-id', 'insert-your-app-secret', {
walletApi: {
authorizationPrivateKey: 'insert-your-authorization-private-key-from-the-dashboard'
}
});
If an authorization private key is passed in the constructor, the Privy client will automatically sign requests with the private key and include the signature as the required privy-authorization-signature
header to Privy's API.
Using the REST API
If requesting Privy's REST API directly, your app must manually sign request payloads with your authorization private key. This involves three steps at a high-level:
- Generate a JSON payload containing the following fields. All fields are required unless otherwise specified.
Field | Type | Description |
---|---|---|
version | 1 | Authorization signature version. Currently, 1 is the only version. |
method | 'POST' | HTTP method for the request. Currently, only 'POST' requests are used. |
url | string | The full URL for the request. Should not include a trailing slash. |
body | JSON | JSON body for the request. |
headers | JSON | JSON object containing any Privy-specific headers, e.g. those that are prefixed with 'privy-' . This should not include any other headers, such as authentication headers, content-type , or trace headers. |
headers['privy-app-id'] | string | Privy app ID header (required). |
- Canonicalize the payload per RFC8785 and serialize it to a string. This GitHub repository links to various libraries for JSON canonicalization in different languages.
- Sign the serialized JSON with ECDSA P-256 using your app's private key and serialize it to a base64-encoded string.
See the code snippets below to serialize and sign requests with your app's private key.
ts
import canonicalize from 'canonicalize'; // Support JSON canonicalization
import crypto from 'crypto'; // Support P-256 signing
// Replace this with your private key from the Dashboard
const PRIVY_AUTHORIZATION_KEY = 'wallet-auth:insert-your-private-key-here';
...
function getAuthorizationSignature({url, body}: {url: string; body: object}) {
const payload = {
version: 1,
method: 'POST',
url,
body,
headers: {
'privy-app-id': 'insert-your-app-id'
}
};
// JSON-canonicalize the payload and convert it to a buffer
const serializedPayload = canonicalize(payload) as string;
const serializedPayloadBuffer = Buffer.from(serializedPayload);
// Replace this with your app's authorization key. We remove the 'wallet-auth:' prefix
// from the key before using it to sign requests
const privateKeyAsString = PRIVY_AUTHORIZATION_KEY.replace('wallet-auth:', '');
// Convert your private key to PEM format, and instantiate a node crypto KeyObject for it
const privateKeyAsPem = `-----BEGIN PRIVATE KEY-----\n${privateKeyAsString}\n-----END PRIVATE KEY-----`;
const privateKey = crypto.createPrivateKey({
key: privateKeyAsPem,
format: 'pem',
});
// Sign the payload buffer with your private key and serialize the signature to a base64 string
const signatureBuffer = crypto.sign('sha256', serializedPayloadBuffer, privateKey);
const signature = signatureBuffer.toString('base64');
return signature;
}
const authorizationSignature = getAuthorizationSignature({
url: 'https://auth.privy.io/api/v1/wallets/rpc',
// Replace with your desired body
body: {
address: '0xb8B849D7647937eB7331Dc7b6C445651A3EC55aE',
chain_type: 'ethereum',
method: 'personal_sign',
params: {
message: 'Hello, Ethereum',
encoding: 'utf-8'
}
},
});
Setting the privy-authorization-signature
header
Once you have signed your request with your authorization keypair, include the produced signature
as the 'privy-authorization-signature'
header for your request.