Auth method linking enables users to associate multiple authentication methods with a single embedded wallet account. This allows users to sign in using different methods (email, SMS, OAuth) while maintaining access to the same wallet and user identity.
Ready to get started? Jump to implementation examples to get a feel for the React components and hooks.
By default, each authentication method creates a separate user identity. For example, if a user signs in with their email and later signs in with their phone number, they would have two different embedded wallets. Auth method linking solves this problem by allowing users to:
Access their wallet using multiple methods: Sign in with email, phone, or social providers interchangeably.
Meet 2FA requirements: For applications that require 2FA, Embedded Wallets provide a smooth integration.
Improve account security: Add additional authentication factors as users accumulate more funds.
Enhance account recovery: Multiple methods provide backup options if one method becomes unavailable.
Important: A user must be signed in before linking additional authentication methods. Users cannot link methods to an unauthenticated session.
The examples below show both React component and hook-based approaches from @coinbase/cdp-react and @coinbase/cdp-hooks. For other implementation approaches, see the Implementation Guide.
Use the useLinkEmail hook to link an email address to the currently authenticated user. This follows the same two-step flow as email sign-in: initiate the flow and then verify the OTP.
Report incorrect code
Copy
Ask AI
import { useLinkEmail, useVerifyEmailOTP, useCurrentUser } from "@coinbase/cdp-hooks";import { useState } from "react";function LinkEmail() { const { linkEmail } = useLinkEmail(); const { verifyEmailOTP } = useVerifyEmailOTP(); const { currentUser } = useCurrentUser(); const [flowId, setFlowId] = useState(""); const handleLinkEmail = async (email: string) => { if (!currentUser) { console.error("User must be signed in first"); return; } try { // Initiate email linking const result = await linkEmail(email); setFlowId(result.flowId); // In a real application, you would prompt the user for the OTP const otp = "123456"; // Verify the OTP to complete linking await verifyEmailOTP({ flowId: result.flowId, otp }); console.log("Email linked successfully!"); } catch (error) { console.error("Failed to link email:", error); } }; return ( <button onClick={() => handleLinkEmail("additional-email@example.com")} disabled={!currentUser} > Link Email </button> );}
Use the useLinkGoogle hook to link a Google account to the currently authenticated user. This initiates the OAuth flow for Google authentication.
Report incorrect code
Copy
Ask AI
import { useLinkGoogle, useCurrentUser } from "@coinbase/cdp-hooks";function LinkGoogleAccount() { const { linkGoogle } = useLinkGoogle(); const { currentUser } = useCurrentUser(); const handleLinkGoogle = async () => { if (!currentUser) { console.error("User must be signed in first"); return; } try { // This initiates the OAuth flow to link a Google account await linkGoogle(); // The user will be redirected to Google for authentication // After successful authentication, the Google account will be linked } catch (error) { console.error("Failed to link Google account:", error); } }; return ( <button onClick={handleLinkGoogle} disabled={!currentUser}> Link Google Account </button> );}
Use the useLinkApple hook to link an Apple account to the currently authenticated user. This initiates the OAuth flow for Apple authentication.
Report incorrect code
Copy
Ask AI
import { useLinkApple, useCurrentUser } from "@coinbase/cdp-hooks";function LinkAppleAccount() { const { linkApple } = useLinkApple(); const { currentUser } = useCurrentUser(); const handleLinkApple = async () => { if (!currentUser) { console.error("User must be signed in first"); return; } try { // This initiates the OAuth flow to link an Apple account await linkApple(); // The user will be redirected to Apple for authentication // After successful authentication, the Apple account will be linked } catch (error) { console.error("Failed to link Apple account:", error); } }; return ( <button onClick={handleLinkApple} disabled={!currentUser}> Link Apple Account </button> );}
Use the useLinkOAuth hook to link an X account to the currently authenticated user. This initiates the OAuth flow for X authentication.
Report incorrect code
Copy
Ask AI
import { useLinkOAuth, useCurrentUser } from "@coinbase/cdp-hooks";function LinkXAccount() { const { linkOAuth } = useLinkOAuth(); const { currentUser } = useCurrentUser(); const handleLinkX = async () => { if (!currentUser) { console.error("User must be signed in first"); return; } try { // This initiates the OAuth flow to link an X account await linkOAuth("x"); // The user will be redirected to X for authentication // After successful authentication, the X account will be linked } catch (error) { console.error("Failed to link X account:", error); } }; return ( <button onClick={handleLinkX} disabled={!currentUser}> Link X Account </button> );}
Use the useLinkOAuth hook to link any supported OAuth provider to the currently authenticated user. This provides a unified interface for all OAuth providers.
Report incorrect code
Copy
Ask AI
import { useLinkOAuth, useCurrentUser } from "@coinbase/cdp-hooks";function LinkOAuthProvider() { const { linkOAuth } = useLinkOAuth(); const { currentUser } = useCurrentUser(); const handleLinkGoogle = async () => { if (!currentUser) { console.error("User must be signed in first"); return; } try { // Link a Google account await linkOAuth("google"); } catch (error) { console.error("Failed to link Google account:", error); } }; const handleLinkApple = async () => { if (!currentUser) return; try { // Link an Apple account await linkOAuth("apple"); } catch (error) { console.error("Failed to link Apple account:", error); } }; const handleLinkX = async () => { if (!currentUser) return; try { // Link an X account await linkOAuth("x"); } catch (error) { console.error("Failed to link X account:", error); } }; return ( <div> <button onClick={handleLinkGoogle} disabled={!currentUser}> Link Google </button> <button onClick={handleLinkApple} disabled={!currentUser}> Link Apple </button> <button onClick={handleLinkX} disabled={!currentUser}> Link X </button> <button onClick={handleLinkCoinbase} disabled={!currentUser}> Link Coinbase </button> </div> );}
OAuth authentication support:
OAuth2 login is currently only supported via web. An upcoming release will add support for React Native.