Using authorization signatures

Authorization signatures protect your resources and wallet operations by cryptographically signing API requests. When enabled, these signatures prevent malicious actors from tampering with your request payload or forging requests to your wallets, ensuring that only authorized servers can trigger wallet actions.

Authorization signatures are a security feature used to secure update requests to all critical resources.

Required headers

When using authorization signatures, include the following header with your request:

privy-authorization-signature
string

The authorization signature. If multiple signatures are required, they should be comma separated.

When are they necessary?

Modifying resources

All critical resources have an owner_id field, which indicates the authorization key or quorum whose signatures are required in order to modify the given resource.

This means, if the owner_id is set, authorization signatures are required for all PATCH and DELETE requests to the resource.

Key quorums do not have owners, but rather require a satisfaying set of signatures from the key quorum itself.

Taking actions with wallets

Signatures from the wallet’s owner are required to take actions on a wallet by default. If an owner_id is set, authorization signatures are required for:

  • POST requests to /api/v1/wallets/<wallet_id>/rpc

You can add additional, non-owner, signers to a wallet by specifying them in the additional_signers field on the wallet resource.

Authorization signatures are an important security measure and we strongly recommend registering authorization keys for all production resources.

Creating authorization keys

To create a new authorization key:

  1. Visit the Authorization keys page for your app in the Dashboard
  2. Click the Generate new key button
  3. Copy and save the generated Authorization key

The private key (e.g. the Authorization key you copy) is generated on your device. Privy only receives the public key for registration. The private key never leaves the client.

Privy also supports registration of P-256 authorization keypairs via the REST API.

Generating signatures

If you’re using Privy’s Server SDK to use server wallets, simply pass your authorization key to the Privy client’s constructor and the SDK will automatically include authorization signatures when required.

Generating an authorization signature involves three steps:

1

Build Payload

Generate a JSON payload containing the following fields. All fields are required unless otherwise specified.

FieldTypeDescription
version1Authorization signature version. Currently, 1 is the only version.
method`‘POST''PUT''PATCH''DELETE’`HTTP method for the request. Signatures are not required on 'GET' requests.
urlstringThe full URL for the request. Should not include a trailing slash.
bodyJSONJSON body for the request.
headersJSONJSON 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']stringPrivy app ID header (required).
headers['privy-idempotency-key']stringPrivy idempotency key header (optional). If the request does not contain an idempotency key, leave this field out of the payload.
2

Format Payload

Canonicalize the payload per RFC 8785 and serialize it to a string. This GitHub repository links to various libraries for JSON canonicalization in different languages.

3

Sign Payload

Sign the serialized JSON with ECDSA P-256 using your app’s private key and serialize it to a base64-encoded string.

Examples

import {PrivyClient} from '@privy-io/server-auth';

const client = new PrivyClient($PRIVY_APP_ID, $PRIVY_APP_SECRET, {
  walletApi: {
    authorizationPrivateKey: $PRIVY_AUTHORIZATION_PRIVATE_KEY
  }
});

const res = await privy.walletApi.ethereum.signMessage({
  walletId: $WALLET_ID,
  message: 'Hello world'
});