> ## Documentation Index
> Fetch the complete documentation index at: https://docs.privacyboost.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Dynamic Integration

> Authenticate Privacy Boost users with Dynamic

# Dynamic Integration

[Dynamic](https://www.dynamic.xyz) provides wallet connection, embedded wallets, and multi-chain auth for web3 apps. You can use Dynamic as your auth provider for Privacy Boost, letting users log in through Dynamic's UI while using Privacy Boost for private transactions.

## How It Works

Dynamic authenticates your users and issues JWTs. Your backend forwards the Privacy Boost login payload with the Dynamic JWT attached. Privacy Boost validates the token against Dynamic's JWKS endpoint using the `custom_jwt` auth method.

<img className="block dark:hidden" src="https://mintcdn.com/sunnysidelabs/npTSPV0krdyxjvTn/images/sdk/dynamic-flow.svg?fit=max&auto=format&n=npTSPV0krdyxjvTn&q=85&s=148237566e2966be7394a8761430ffdb" alt="Dynamic Authentication Flow" width="800" height="400" data-path="images/sdk/dynamic-flow.svg" />

<img className="hidden dark:block" src="https://mintcdn.com/sunnysidelabs/npTSPV0krdyxjvTn/images/sdk/dynamic-flow-dark.svg?fit=max&auto=format&n=npTSPV0krdyxjvTn&q=85&s=f74bb6c20834520edc0b13212a6c0062" alt="Dynamic Authentication Flow" width="800" height="400" data-path="images/sdk/dynamic-flow-dark.svg" />

## Server-Side Setup

Your app must be configured with the `custom_jwt` auth method. Contact the Privacy Boost team with:

* **JWKS URL** — Dynamic's JWKS endpoint for your environment: `https://app.dynamic.xyz/api/v0/sdk/<YOUR_ENVIRONMENT_ID>/.well-known/jwks`
* **Issuer** — Required expected `iss` claim: `app.dynamic.xyz/<YOUR_ENVIRONMENT_ID>`
* **Audience** — Required expected `aud` claim from your Dynamic access token. This is the token audience, not the `environment_id` claim.

The backend configuration looks like:

```json theme={null}
{
  "jwks_url": "https://app.dynamic.xyz/api/v0/sdk/<ENVIRONMENT_ID>/.well-known/jwks",
  "issuer": "app.dynamic.xyz/<ENVIRONMENT_ID>",
  "audience": "<DYNAMIC_TOKEN_AUDIENCE>"
}
```

<Info>
  Find your Environment ID in the [Dynamic Dashboard](https://app.dynamic.xyz) under Developer > SDK & API Keys.
  Decode a representative Dynamic access token and configure `audience` to match its exact `aud` claim. Do not use the `environment_id` claim unless your token's `aud` is actually the same value.
</Info>

## Client-Side Integration

### 1. Set Up Dynamic

Follow [Dynamic's React quickstart](https://www.dynamic.xyz/docs/react) to set up `DynamicContextProvider`:

```tsx theme={null}
import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core';
import { EthereumWalletConnectors } from '@dynamic-labs/ethereum';

function App() {
  return (
    <DynamicContextProvider
      settings={{
        environmentId: 'your-environment-id',
        walletConnectors: [EthereumWalletConnectors],
      }}
    >
      <YourApp />
    </DynamicContextProvider>
  );
}
```

### 2. Create a Token Provider

The token provider gets the Dynamic auth token and forwards it with the Privacy Boost login payload:

```typescript theme={null}
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';

function usePrivacyBoostAuth() {
  const { authToken } = useDynamicContext();

  const tokenProvider = async (loginPayload: any) => {
    if (!authToken) throw new Error('Not logged in to Dynamic');

    const res = await fetch('https://your-backend.com/api/privacy-boost/auth', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${authToken}`,
      },
      body: JSON.stringify(loginPayload),
    });

    return await res.json(); // { token, expiresIn }
  };

  return { tokenProvider };
}
```

### 3. Authenticate with Privacy Boost

```typescript theme={null}
const { tokenProvider } = usePrivacyBoostAuth();

await sdk.auth.authenticate(adapter, {
  type: 'walletDerived',
  tokenProvider,
});
```

### 4. Implement the Backend Endpoint

Your backend receives the SDK's login payload, and forwards to Privacy Boost with the Dynamic JWT:

```typescript theme={null}
app.post('/api/privacy-boost/auth', async (req, res) => {
  // 1. Extract Dynamic token from Authorization header
  const dynamicToken = req.headers.authorization?.replace('Bearer ', '');
  if (!dynamicToken) return res.status(401).json({ error: 'Missing Dynamic token' });

  // 2. Forward to Privacy Boost with the Dynamic JWT attached
  const pbResponse = await fetch('https://optimism.sepolia.privacyboost.io/auth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      ...req.body,                   // SDK's login payload
      custom_jwt_token: dynamicToken, // Dynamic JWT — validated via JWKS
    }),
  });

  const data = await pbResponse.json();
  res.json({
    token: data.access_token,
    expiresIn: data.expires_in,
  });
});
```

### Using Dynamic's Wallet Connector

If your users connect wallets through Dynamic, you can use the connected wallet's provider with the Privacy Boost SDK:

```typescript theme={null}
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';

function usePrivacyBoostWithDynamic() {
  const { primaryWallet } = useDynamicContext();

  const getAdapter = async () => {
    if (!primaryWallet) throw new Error('No wallet connected');
    const provider = await primaryWallet.getWalletClient();

    return {
      async connect() {
        const accounts = await provider.request({ method: 'eth_requestAccounts' });
        const chainId = await provider.request({ method: 'eth_chainId' });
        return { address: accounts[0], chainId: parseInt(chainId, 16) };
      },
      async disconnect() {},
      async signMessage(message: string) {
        const accounts = await provider.request({ method: 'eth_accounts' });
        return provider.request({ method: 'personal_sign', params: [message, accounts[0]] });
      },
      async signTypedData(typedData: string) {
        const accounts = await provider.request({ method: 'eth_accounts' });
        return provider.request({ method: 'eth_signTypedData_v4', params: [accounts[0], typedData] });
      },
      async sendTransaction(tx: unknown) {
        return provider.request({ method: 'eth_sendTransaction', params: [tx] });
      },
      async getAddress() {
        const accounts = await provider.request({ method: 'eth_accounts' });
        return accounts[0];
      },
      async getChainId() {
        const chainId = await provider.request({ method: 'eth_chainId' });
        return parseInt(chainId, 16);
      },
    };
  };

  return { getAdapter };
}
```

## Next Steps

Continue with setup:

* [Key Management](/sdk/concepts/key-management) — Configure key persistence for returning users
* [Error Handling](/sdk/concepts/error-handling) — Handle auth and operation errors

Or explore other auth methods:

* [Custom JWT](/sdk/guides/custom-jwt) — For Auth0, Firebase, Supabase, Clerk, or OIDC providers
* [Privy](/sdk/guides/privy) — For Privy social login and embedded wallets
