Overview

Embedded Wallets provide secure, user-friendly authentication methods that eliminate the complexity of traditional crypto wallets. Users can access their wallets through familiar authentication patterns like email one-time passwords (OTP), without ever dealing with seed phrases or browser extensions.
Looking for the technical implementation? Check out our Quickstart Guide for step-by-step integration instructions.

Email OTP

Email OTP is the primary authentication method for Embedded Wallets, providing a secure and familiar experience for users.

Authentication approaches

There are three ways to implement authentication in your application:
  1. AuthButton component from @coinbase/cdp-react: Pre-built UI component (fastest integration)
  2. React hooks from @coinbase/cdp-hooks: For custom React UIs with state management
  3. Direct methods from @coinbase/cdp-core: For vanilla JavaScript/TypeScript or non-React frameworks
Important authentication considerations:
  • Always check if a user is already signed in before starting a new authentication flow. Attempting to call verifyEmailOTP while a user is already authenticated will result in an error and may leave the application in an inconsistent state.
  • To sign out users, use the signOut() method from @coinbase/cdp-core or the AuthButton component which handles sign out automatically.

AuthButton component (simplest)

For the fastest integration, @coinbase/cdp-react provides a pre-built AuthButton component that handles the entire authentication flow with a single line of code.
For more CDP React components and styling options, see the React Components documentation.
import { CDPReactProvider } from "@coinbase/cdp-react";
import { AuthButton } from "@coinbase/cdp-react/components/AuthButton";
import { type Config } from "@coinbase/cdp-core";

const config: Config = {
  projectId: "your-project-id"
};

function App() {
  return (
    <CDPReactProvider config={config}>
      <YourApp />
    </CDPReactProvider>
  );
}
The AuthButton component automatically:
  • Shows “Sign In” when the user is not authenticated
  • Shows “Sign Out” when the user is authenticated
  • Handles the entire email OTP flow internally
  • Manages loading and error states
  • Follows your theme configuration
This is the recommended approach for most applications that want a quick, production-ready authentication experience.

React hooks

For React applications, @coinbase/cdp-hooks provides convenient hooks that handle state management and re-renders automatically.
import { CDPHooksProvider } from "@coinbase/cdp-hooks";
import { type Config } from "@coinbase/cdp-core";

const config: Config = {
  projectId: "your-project-id"
};

// Wrap your app with the provider
function App() {
  return (
    <CDPHooksProvider config={config}>
      <YourApp />
    </CDPHooksProvider>
  );
}
The React hooks automatically handle loading states, error states, and re-renders when authentication state changes. They’re the recommended approach for React applications.

Direct methods

The @coinbase/cdp-core package provides the low-level authentication primitives for maximum control over the user experience. This approach is ideal for non-React applications or when you need fine-grained control.
import { initialize, signInWithEmail, verifyEmailOTP } from '@coinbase/cdp-core';

// Step 1: Initialize the CDP SDK
await initialize({
  projectId: 'your-project-id'
});

// Step 2: Initiate email authentication
const { flowId, message } = await signInWithEmail({
  email: 'user@example.com'
});
console.log(message); // "OTP sent to user@example.com"

// Step 3: Verify the OTP code
const { user, isNewUser } = await verifyEmailOTP({
  flowId,
  otp: '123456'
});

// User is now authenticated and has access to their wallet
console.log('User ID:', user.userId);
console.log('EVM Addresses:', user.evmAccounts);
console.log('Is new user:', isNewUser);
Always handle authentication errors gracefully. Common errors include:
  • Invalid or expired OTP codes
  • Rate limiting for too many attempts
  • Network connectivity issues
  • Invalid project configuration

SMS OTP (coming soon)

SMS-based one-time passwords will be available as an additional authentication method, providing users with more flexibility in how they access their wallets.
SMS OTP authentication is currently in development. Join our Discord to be notified when it becomes available.

Developer-delegated authentication

For applications with existing authentication systems, we offer developer-delegated authentication on a case-by-case basis. This allows you to integrate Embedded Wallets seamlessly with your current user authentication flow.

How it works

  1. Your authentication: Users authenticate with your existing system
  2. Secure handoff: Your backend securely communicates user identity to CDP
  3. Wallet creation: CDP creates or retrieves the user’s wallet based on your authentication
  4. Seamless experience: Users never leave your application or see CDP authentication screens

Benefits

  • Consistent UX: Maintain your existing authentication experience
  • Single sign-on: Users don’t need separate authentication for their wallet
  • Enhanced security: Leverage your existing security infrastructure
  • Compliance ready: Meet your specific regulatory requirements

Getting access

Developer-delegated authentication requires custom integration and security review. To request access:
1

Evaluate your needs

Ensure you have:
  • An existing authentication system
  • Backend infrastructure for secure communication
  • Specific compliance or UX requirements that standard authentication doesn’t meet
2

Contact our team

Message us in the #server-wallets channel on Discord
3

Integration review

Our team will work with you to:
  • Review your authentication architecture
  • Design a secure integration approach
  • Provide custom SDK configuration
  • Support your implementation

Best practices

Security recommendations

  1. Domain allowlisting: Always configure your allowed domains in CDP Portal
  2. HTTPS only: Never use embedded wallets on non-HTTPS sites in production
  3. Rate limiting: Implement rate limiting on your authentication endpoints
  4. Session management: Use appropriate session timeouts for your use case

State management

  1. Always check authentication state: Before starting any authentication flow, verify if the user is already signed in:
    const user = await getCurrentUser();
    if (user) {
      // User is already authenticated
      return;
    }
    
  2. Implement sign out: Provide a clear way for users to sign out:
    import { signOut } from '@coinbase/cdp-core';
    
    // Sign out the current user
    await signOut();
    
    For React applications, use the AuthButton component which handles sign out automatically, or the useSignOut hook:
    import { useSignOut } from '@coinbase/cdp-hooks';
    
    function SignOutButton() {
      const { signOut } = useSignOut();
      return <button onClick={signOut}>Sign Out</button>;
    }
    
  3. Avoid redundant verification: Don’t call verifyEmailOTP when a user is already authenticated. This will result in an error and may leave your application in an inconsistent state.

User experience tips

  1. Clear messaging: Explain why users need to verify their email
  2. Error handling: Provide helpful error messages for common issues
  3. Loading states: Show progress during authentication steps
  4. Success feedback: Confirm when authentication is complete

Choosing the right approach