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

Every app brings to life a different product vision and as such has to account for different considerations in how users interact with them. App experiences vary, and UX is not one size fits all.

At Privy, we recognize that this means different apps will make different tradeoffs in terms of where to introduce friction for the user in helping them set up and secure their accounts. We exist to help developers manage these tradeoffs, but we must also help them enforce appropriate defaults.

It is worth noting that "automatic recovery" mode makes for smooth user UX (without needing to set up a recovery system upfront when logging in) but it comes with tradeoffs. Notably, the root of trust with “automatic recovery” is the user’s authentication token. This means access to the auth token grants access to the wallet. Accordingly, this token must be properly secured at all times.

We recommend enabling password-based recovery for users. This is especially important to enforce as the value of assets in a user's wallet grows. We are working on a range of solutions to improve on these tradeoffs for your app and users.

Key Management

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 iframe's local storage.
  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 is encrypted either by user-provided entropy (a strong password) or by Privy. Recovery shares are only ever encrypted or decrypted on the user's device.
    • If encrypted by user-provided entropy, only the user can decrypt the recovery share. Privy never sees this share or the user's password.
    • If encrypted by Privy, Privy uses an encryption key generated locally and secured via an isolated service. The encryption key can only be accessed if the decryption request includes the user's auth token.

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.

WARNING

In the case you do not require a passcode from your users, you are trusting Privy's infrastructure as well as setting the user's authentication token as the sole root of trust for their wallet. We generally recommend you prompt users to set a recovery passcode upfront, especially as assets in a wallet grow.

INFO

Threat models, like UX, are not one-size-fits-all. 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.

These tradeoffs will improve over time and we are actively building out support for further options, including passkeys or storing the encrypted recovery share in a user's cloud account or password manager.

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:

  • prompting the user to enter their passcode, if using user-entropy for recovery
  • requesting the recovery decryption key using the user's auth token, if using automatic 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.

Wallet recovery

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. This even works if Privy is offline.

  • 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 [email protected].