Skip to main content

Overview

Custom authentication enables applications with existing authentication systems to integrate Embedded Wallets seamlessly. Instead of using CDP’s built-in authentication methods (email OTP, SMS, OAuth), you can use JSON Web Tokens (JWTs) from your own Identity Provider. This approach is ideal when:
  • You already have users authenticated via Auth0, Firebase, AWS Cognito, or a custom solution
  • You want to implement single sign-on (SSO) across your entire platform
  • You need to integrate with corporate identity systems
  • You must use specific authentication providers for regulatory compliance

How it works

Custom authentication follows a straightforward flow that leverages your existing identity infrastructure:
Before users can authenticate, you configure your JWKS (JSON Web Key Set) endpoint in the CDP Portal. This allows CDP to verify the authenticity of JWTs issued by your Identity Provider.
  1. User logs in: The user authenticates with your existing authentication system (Auth0, Firebase, etc.)
  2. JWT generation: Your Identity Provider generates a valid JWT for the authenticated user
  3. CDP integration: Your application provides the JWT to CDP via the customAuth.getJwt callback
  4. JWT validation: CDP retrieves your JWKS endpoint (configured in Portal), validates the JWT signature, and checks required claims (iss, sub, exp, iat)
  5. Wallet access: Upon successful validation, CDP uses the stable, verified sub claim (user ID) to get or create an embedded wallet for the user
Unlike CDP’s built-in authentication, custom auth sessions are managed entirely by your Identity Provider:
  • CDP always requests a fresh JWT via the getJwt callback when needed
  • Token refresh is handled by your IDP, not CDP
  • Session duration is controlled by your IDP’s configuration
  • Users must sign out from both your IDP and CDP

Prerequisites

Before implementing custom authentication, ensure you have:

CDP Portal configuration

  • A CDP project with a Project ID
  • Your JWKS endpoint configured in the CDP Portal (see Portal Configuration below)

Identity Provider requirements

Your Identity Provider must support:
  • JWKS (JSON Web Key Sets) with RS256 or ES256 signing algorithms
  • Required JWT claims:
    • iss (issuer): Your Identity Provider’s domain
    • sub (subject): Unique identifier that identifies the particular user on your application
    • exp (expiration): Token expiration timestamp
    • iat (issued at): Token issuance timestamp

Portal Configuration

To configure custom authentication in the CDP Portal:
  1. Navigate to your project in the CDP Portal
  2. Locate your custom authentication settings under your project configuration
CDP Portal Custom Auth Configuration
  1. Enable custom authentication by switching on the toggle if you had not yet
  2. Add your JWKS endpoint URL
    • For example, it may look like https://YOUR_DOMAIN.auth0.com/.well-known/jwks.json if you are using Auth0 as your IDP
  3. Configure expected claims:
    • Issuer (iss): Your Identity Provider’s domain. Note that you are required to specify the issuer.
    • Audience (aud): Your API or app identifier
  4. Save your configuration
Important considerations:
  • Ensure your JWKS endpoint is publicly accessible over HTTPS. CDP needs to fetch your public keys to validate JWT signatures.
  • Once custom authentication is enabled for a project, standard authentication methods (email OTP, SMS, OAuth) are not available, and vice versa. You cannot use both simultaneously.

SDK Integration

The CDP Frontend SDK provides built-in support for custom authentication through the customAuth configuration option.

React integration

For React applications, use CDPHooksProvider or CDPReactProvider with the customAuth configuration:
import { CDPHooksProvider } from '@coinbase/cdp-hooks';
import { useAuth0 } from '@auth0/auth0-react';

function AppWrapper() {
  const { getAccessTokenSilently } = useAuth0();

  return (
    <CDPHooksProvider
      config={{
        projectId: 'your-project-id',
        customAuth: {
          getJwt: getAccessTokenSilently
        },
        ethereum: {
          createOnLogin: 'eoa'
        }
      }}
    >
      <YourApp />
    </CDPHooksProvider>
  );
}

Non-React integration

For vanilla JavaScript/TypeScript or other frameworks, use the initialize method from @coinbase/cdp-core:
import { initialize } from '@coinbase/cdp-core';

await initialize({
  projectId: 'your-project-id',
  customAuth: {
    getJwt: async () => {
      try {
        return await auth0.getTokenSilently();
      } catch (error) {
        console.error('Failed to get token:', error);
        return undefined;
      }
    }
  }
});
The getJwt callback is called automatically by CDP whenever authentication is needed. It should return a fresh JWT from your Identity Provider or undefined if the user is not authenticated.

Authentication flow

Once you’ve configured custom authentication, you need to explicitly authenticate the user with CDP after they log in with your Identity Provider.

Triggering authentication

After your user logs in with your IDP (Auth0, Firebase, etc.), call authenticateWithJWT() to authenticate with CDP:
  • First-time users: CDP will create a new embedded wallet for the user (based on their sub claim)
  • Returning users: CDP will retrieve their existing wallet (using the same sub claim)
import { useAuthenticateWithJWT } from '@coinbase/cdp-hooks';
import { useAuth0 } from '@auth0/auth0-react';

function LoginComponent() {
  const { authenticateWithJWT, isLoading } = useAuthenticateWithJWT();
  const { loginWithRedirect, isAuthenticated } = useAuth0();

  const handleLogin = async () => {
    // First, log in with your IDP (Auth0 in this example)
    await loginWithRedirect();
  };

  // After Auth0 login completes, authenticate with CDP
  React.useEffect(() => {
    if (isAuthenticated) {
      authenticateWithJWT()
        .then(() => console.log('Successfully authenticated with CDP'))
        .catch((error) => console.error('CDP authentication failed:', error));
    }
  }, [isAuthenticated, authenticateWithJWT]);

  return (
    <button onClick={handleLogin} disabled={isLoading}>
      {isLoading ? 'Authenticating...' : 'Sign In'}
    </button>
  );
}

Accessing wallet data

Once authenticated with CDP, you can access the user’s wallet:
import { useCurrentUser, useEvmAccount } from '@coinbase/cdp-hooks';

function WalletComponent() {
  const { currentUser } = useCurrentUser();
  const { account } = useEvmAccount();

  if (!currentUser) {
    return <p>Please sign in with your account</p>;
  }

  return (
    <div>
      <p>User ID: {currentUser.id}</p>
      <p>Wallet Address: {account?.address}</p>
    </div>
  );
}

Monitoring authentication state

Use the useIsSignedIn hook to monitor authentication state:
import { useIsSignedIn } from '@coinbase/cdp-hooks';

function App() {
  const { isSignedIn } = useIsSignedIn();

  return (
    <div>
      {isSignedIn ? (
        <p>You are signed in</p>
      ) : (
        <p>Please sign in</p>
      )}
    </div>
  );
}

Session management

Custom authentication sessions differ from CDP’s built-in authentication in several key ways:

Token lifecycle

  • Managed by your Identity Provider: Session duration, token expiration, and refresh are controlled by your Identity Provider
  • Always fresh: CDP calls getJwt whenever it needs authentication, ensuring tokens are always current
  • No CDP refresh: CDP does not store or refresh tokens, it relies entirely on your getJwt callback
  • Maximum TTL: JWTs must have an expiration time (exp) within 7 days from issuance

Sign out

When using custom authentication, users must sign out from both your Identity Provider and CDP:
import { useSignOut } from '@coinbase/cdp-hooks';
import { useAuth0 } from '@auth0/auth0-react';

function SignOutButton() {
  const { signOut: cdpSignOut } = useSignOut();
  const { logout: auth0Logout } = useAuth0();

  const handleSignOut = async () => {
    // Sign out from CDP first
    await cdpSignOut();

    // Then sign out from Auth0
    auth0Logout({
      returnTo: window.location.origin
    });
  };

  return <button onClick={handleSignOut}>Sign Out</button>;
}
For more details on session management, see the Session Management guide.

Testing and debugging

Verify JWT structure

Before integrating with CDP, verify your JWT contains the required claims:
  1. Obtain a JWT from your Identity Provider
  2. Decode it using jwt.io or similar tool
  3. Verify claims:
    • iss: Matches your configured issuer
    • sub: Contains a unique, stable user ID
    • exp: Token expiration is in the future
    • iat: Token issuance timestamp
    • aud: Matches your configured audience
Example JWT payload:
{
  "iss": "https://example.auth0.com/",
  "sub": "auth0|1234567890",
  "aud": [
    "test-app"
  ],
  "exp": 1700000000,
  "iat": 1699996400
}

Validate JWKS endpoint

Ensure your JWKS endpoint is accessible and returns valid keys:
  1. Access your JWKS URL in a browser (e.g., https://example.auth0.com/.well-known/jwks.json)
  2. Verify the response contains public keys

Complete example

A complete working example with Auth0 integration will later be added here.