Skip to content

Security

The security of your users' data and digital assets is our top priority at Privy. We recognize our role as a critical dependency for our customers' apps and greatly appreciate the responsibility that comes with that.

Privy's internal architecture and infrastructure has gone through several rounds of security reviews, audits, and pentesting, which you can read more about here. We treat security as a constantly-moving target, and undergo these reviews and audits on a regular basis to surface and address new issues.

Implementing, maintaining, and testing security in your app is a huge undertaking. We've taken careful effort to use the best practices for securing your users' data and digital assets.

Below, you can read more about some of these practices:

App Authentication

Methods

Privy supports multiple methods for authenticating your end-users and verifying their identity. Today, this includes:

We do not support regular password-based verification given users' tendencies to use and reuse easy-to-guess passwords, and the high incidence of password database breaches.

Tokens

Once a user verifies their identity through one of the methods listed above, Privy issues the user an access token and a refresh token to store the user's authenticated session in your app.

Access Token

The access token is a JSON Web Token (JWT) signed by a Privy Ed25519 key specific to your app. This signature ensures that this token could have only been produced by Privy, and cannot be spoofed. In your frontend, Privy uses this access token to determine whether the user is authenticated or not. Your backend should use the access token on incoming requests to determine if the request originated from an authenticated user.

The access token has a lifetime of one hour, to ensure that authenticated sessions can be easily revoked and to restrict the window of vulnerability in the unlikely case that the access token is exposed outside of your app.

Refresh Token

The refresh token is used to refresh the user's session once their access token has expired. It has a lifetime of 30 days, to ensure that users don't have to frequently login again, but can only be used once. This ensures that the refresh token can only be used to refresh an existing session, and never to create an entirely new session.

If the Privy SDK detects that the access token or refresh token has been tampered with, it will immediately log the user out and will destroy the corresponding session in Privy's backend.

User Data Management

Encryption and Backups

All of Privy's databases are encrypted at rest. Privy takes full database snapshots daily and uploads transaction logs for database instances to backup storage every 5 minutes. These snapshots are stored for 7 days, meaning Privy can safely restore databases to any point in the last week (with 5 minute granularity) as needed.

TLS Encryption and Traffic Management

All traffic is encrypted with a minimum supported TLS version of 1.2 and HSTS. All traffic to the Privy dashboard (https://dashboard.privy.io), the Privy API (https://auth.privy.io), and related subdomains is routed through Cloudflare. All of Privy's servers run within private VPCs on AWS.

API Authentication

All requests to Privy's API to query or update user data must be authenticated by the app's API secret. This secret is never stored in a Privy database and cannot be recovered after it has been generated by the app developer.

Embedded Wallets

TIP

Privy embedded wallets are fully self-custodial and easy to integrate in only a few lines of code. Neither Privy nor integrating applications ever access embedded wallet private keys.

Architecture and Custody

Privy's embedded wallets have three core components:

  • the Privy API, which stores wallet metadata for a given user, such as their wallet address
  • the isolated iframe, which manages the user's private key and handles wallet operations
  • the Privy SDK, which exposes a high-level interface for apps to interact with the embedded wallet.
Pregenerate user wallets
Architecture of the embedded wallet

By design, the embedded wallet's private key is only ever stored in-memory within the isolated iframe. The private key is never saved to any database and does not persist past the iframe's lifetime.

The iframe runs on an entirely separate domain from your app. Since modern browsers partition storage across domains, this design ensures that neither your app's code nor the Privy SDK can access the raw private key. Put simply, embedded wallets are strictly non-custodial, for both your app and Privy.

INFO

Threat models, like UX, are context- and app-dependent. Depending on your application, the users you serve and the digital assets they interact with, your requirements for threat models and UX will vary. In kind, Privy offers multiple secure recovery options across the spectrum of threat models, to allow you to choose what's right for your app.

Key management

The section below describes how the private key for the user's wallet is generated and secured.

Creating and splitting the private key

When a user creates an embedded wallet, the isolated iframe securely generates a public-private keypair for the user by choosing 128 bits of entropy at random using a CSPRNG, and converting the bits to a mnemonic via BIP-39. From this mnemonic, the iframe then derives the wallet's public key (and by extension, the wallet address) and private key.

The iframe then splits the private key into three shares using Shamir's secret sharing:

  1. Device share, which is persisted on the user's device. In a browser environment, this is stored in the browser's local storage via the iframe.
  2. Auth share, which is encrypted and stored by Privy. The Privy SDK will retrieve this share for a user when they log in to your app.
  3. Recovery share, which can be automatically secured by Privy's key management system or by the user directly.

The full private key is only ever assembled in-memory, and is never persisted anywhere. At least two of three shares must be present to constitute the full private key.

Securing the recovery share

At a high-level, Privy offers two modes for recovery: automatic and user-managed. These modulate how the recovery share of the user's wallet is secured.

With automatic recovery, Privy implements a key management system to secure the encrypted recovery share on behalf of the user. This allows the user to automatically recover their wallet on a new device as needed, removing the need for them to manage recovery share encryption. Privy's key management infrastructure enforces that only the user can decrypt their recovery share on their device and is set up to prevent any unauthorized access.

WARNING

When using automatic recovery, you are trusting Privy's infrastructure to secure the user's recovery share, and the user's authentication token as the sole root of trust for their wallet.


As assets in your user's wallets grow, we generally recommend that you prompt them to set up a user-managed recovery method.

With user-managed recovery, the recovery share is encrypted via a recovery factor managed by the user. This takes two forms:

  • Passwords: users can set a strong memorable password to secure the recovery share for their wallet. Privy has no knowledge of the user's password and cannot decrypt the recovery share.
  • Cloud-backup: the recovery share is secured by a secret that is backed up to the user's cloud storage account (e.g. Google Drive or iCloud). Privy cannot access the recovery secret from the user's cloud storage account and cannot decrypt the recovery share.

Using the private key

When the embedded wallet needs to use the private key to produce a signature, the Privy SDK will pass the message for the signature to the isolated iframe. The iframe will then reconstitute the private key in-memory, using the device share and the auth share, to compute the signature using ECDSA. The iframe then passes the signature back to the Privy SDK and flushes the assembled private key from memory.

Using the private key on a new device

When a user accesses your app on a new device, the iframe will retrieve the auth share for your user during the login process. Then, depending on how you've configured recovery, the iframe will decrypt the recovery share for your user by:

  • requesting the recovery decryption key using the user's auth token, if using automatic recovery
  • having the user decrypt the key using their recovery factor (password or cloud account), if using user-managed recovery

With the auth share and the recovery share, the iframe is then able to compute a new device share for the new device. This device share allows your user to continue using the wallet on that device, without needing to repeatedly recover it.

Recovery outside Privy

With Privy's architecture, a user is able to recover their private key even if they lose their device or if they lose access to your app.

  • If the user loses access to their device and is unable to retrieve their device share, they can combine their auth share and decrypt their recovery share to reconstitute the full private key.
  • If the user loses access to your app and is unable to retrieve their auth share, they can combine their device share and decrypt their recovery share to reconstitute the full private key.

In all of these cases, Privy rotates keys to ensure compromised devices or authentication methods cannot be combined to maliciously reconstitute the private key.

Third-Party Reviews

Privy's internal infrastructure has undergone multiple rounds of audits by third-party testers and developers, as well as a round of pentesting. Security is a constantly moving target and no system is secure in perpetuity. We regularly undergo audits to surface and address new issues.

All of Privy’s cryptographic libraries (notably around Shamir's secret sharing) are open-sourced and have undergone external audits. The audit reports are linked in the GitHub repo.

If you are a security researcher and would like to reach out to us, please do so using our vulnerability disclosure program. For more information, you can get in touch with our team at security@privy.io.