This guide shows you how to implement Privy authentication and wallets in your Chrome extension using Privy’s React SDK. Chrome extensions offer a unique application experience for your users, but come with some unique nuances specifically around social login.

Set up your Chrome extension project

First, create a React app and install Privy:
npm create react-app my-extension
cd my-extension
npm install @privy-io/react-auth
Create your manifest.json file in the public directory:
{
  "manifest_version": 3,
  "name": "My Extension with Privy",
  "version": "1.0",
  "description": "Chrome extension with Privy authentication",
  "permissions": ["identity", "storage"],
  "host_permissions": ["https://auth.privy.io/*"],
  "action": {
    "default_popup": "index.html",
    "default_title": "My Extension"
  },
  "options_page": "options.html",
  "web_accessible_resources": [
    {
      "resources": ["static/js/*.js", "static/css/*.css"],
      "matches": ["<all_urls>"]
    }
  ]
}
The identity permission is required for OAuth flows, and storage is recommended for persisting user sessions.

Content Security Policy

Below are some guidelines for securing your extension. You can find more information in the Chrome extension security documentation.

Configure your Privy dashboard

You’ll get your extension ID after loading the extension in Chrome’s developer mode at chrome://extensions/.
In the Privy dashboard, configure OAuth settings for your extension: 1. Add allowed origins Go to App Settings > Domains and add:
chrome-extension://<your-extension-id>
2. (Optional) Configure redirect URLs
Use chrome.identity.getRedirectURL() to get the exact redirect URL programmatically.
If your extension uses social login, you’ll need to configure redirect URLs. In your allowed domains, add the following redirect URL, and additionally in your allowed redirect URLs
https://<your-extension-id>.chromiumapp.org/

Enabling social login in your extension

Chrome extensions can’t handle social OAuth flows directly in the popup due to security restrictions. Social login requires opening either the options page or a popup window. This provides the full browser context needed for OAuth redirects. Both approaches follow the same flow:
  1. User clicks “Sign in with social” in extension
  2. Open authentication context (options page or popup window)
  3. Privy handles the OAuth flow
  4. User is redirected back to the extension authenticated
1

User initiates social login

Approach 1: Options page

Setup: Add to your manifest:
{"options_page": "options.html"}
Implementation:
// In your popup component
const openOptionsForLogin = () => {
  chrome.tabs.create({
    url: chrome.runtime.getURL('options.html')
  });
};

Approach 2: Popup window

Implementation:
// In your popup component
const openAuthWindow = () => {
  chrome.windows.create({
    url: chrome.runtime.getURL('auth.html'),
    type: 'popup',
    width: 400,
    height: 600
  });
};
2

Open authentication context (options page or popup window)

Both approaches use the same authentication logic:
You can use the same AuthComponent for both approaches - just render it in different HTML files (options.html or auth.html).
// src/auth/AuthComponent.tsx
import {PrivyProvider, usePrivy, useLogin} from '@privy-io/react-auth';
import {useEffect} from 'react';

const AuthContent = () => {
  const {authenticated, ready} = usePrivy();
  const {login} = useLogin({
    onComplete: () => {
      // Open the extension popup after authentication
      chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
        if (tabs[0]) {
          // Open the extension popup
          chrome.action.openPopup();
        }
      });
    }
  });

  // Auto-trigger login when opened for authentication
  useEffect(() => {
    if (ready && !authenticated) {
      login();
    }
  }, [authenticated, ready]);

  return null;
};

export const AuthComponent = () => (
  <PrivyProvider
    appId="<INSERT_YOUR_APP_ID_HERE>"
    config={{
      appearance: {
        loginMethods: ['google', 'apple', 'email', 'sms', 'twitter']
      }
    }}
  >
    <AuthContent />
  </PrivyProvider>
);
3

Redirect back to the extension

Redirect the user back to the extension after authentication.
    onComplete: () => {
      // Open the extension popup after authentication
      chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
        if (tabs[0]) {
          // Open the extension popup
          chrome.action.openPopup();
        }
      });
    },

That’s it! 🎉

You’ve now implemented Privy authentication in your Chrome extension.

Production considerations

Before publishing to the Chrome Web Store:
  1. Remove unnecessary permissions from manifest
  2. Update OAuth configuration with production URLs in Privy dashboard
  3. Ensure CSP compliance for Chrome extension security policies
Chrome extensions with OAuth require Google’s review. Document your authentication flow and privacy practices clearly in your Web Store listing.