Appearance
Using a custom auth provider
Privy's embedded wallets are fully-compatible with any authentication provider that supports JWT-based, stateless authentication. If you're looking to add embedded wallets to your app, you can either:
- use Privy as your authentication provider (easy to set up out-of-the-box)
- use a custom authentication provider (easy to integrate alongside your existing stack)
INFO
To make these instructions concrete, this guide uses Auth0 as a sample custom auth provider that you can integrate alongside Privy. In practice, you can integrate any auth provider that supports stateless, JWT-based authentication.
If you have questions on how to follow these instructions for your specific auth provider, please reach out!
1. Register your auth provider's information in the Privy dashboard
Register the details from your custom auth provider in the Privy Dashboard per the guide here!
Why does Privy need this information?
When a user logs into your app, your auth provider issues them an access and/or an identity token to represent their auth status. To provision your user's embedded wallet, Privy must validate this token to authenticate your user. Privy will verify both the token's signature and its expiration time (exp
claim).
2. Install the Privy SDK
In your app, run the following command to install the latest version of the @privy-io/expo
SDK:
sh
npm i @privy-io/expo@latest
3. Add the PrivyProvider
to your app
The PrivyProvider
is a React context that allow all components wrapped by the PrivyProvider
to access the Privy SDK, via the usePrivy
hook.
This example assumes your app:
- determines a user's auth status on the client, and can get the user's access/identity token on the client
- uses Auth0 via their client-side SDK (
react-native-auth0
)
(1) Wrap the PrivyProvider
in a custom component
To start, we'll create a custom component to wrap the PrivyProvider
and configure it. This allows you more easily abstract away the configuration of Privy alongside your auth provider.
Create a new component (e.g. EmbeddedWalletProvider.tsx
) and add the following code:
tsx
import {useMemo, type PropsWithChildren, useCallback} from 'react';
import {useAuth0} from 'react-native-auth0';
import {PrivyProvider} from '@privy-io/expo';
const EmbeddedWalletProvider: React.FC<PropsWithChildren> = ({children}) => {
// Get auth details from Auth0
const {user: auth0User, isLoading, getCredentials} = useAuth0();
// Wrap getCredentials as necessary (explained below)
const getCustomToken = useCallback(async () => {
const creds = await getCredentials();
return creds?.idToken;
}, [isLoading, auth0User, getCredentials]);
return (
<PrivyProvider
appId="insert-your-privy-app-id"
config={{
// CUSTOM AUTH CONFIGURATION
customAuth: {
enabled: true,
// The `isLoading` boolean from Auth0's `useAuth0` indicates if Auth0 is currently
// updating the user's auth state on the client or not
isLoading: isLoading,
// The `getCustomToken` callback allows us to get the user's access/identity token
// whenever their auth state changes
getCustomAccessToken: getCustomToken,
},
}}
>
{children}
</PrivyProvider>
);
};
export default EmbeddedWalletProvider;
For the PrivyProvider
's appId
prop, pass in your Privy App ID from the Privy Dashboard.
For the PrivyProvider
's config.customAuth
, pass in the object as defined in the code snippet above. In particular, this object requires:
- an
isLoading
boolean to determine whether the auth provider is actively updating your user's auth state in the client or not- For example, directly pass in the
isLoading
variable from Auth0'suseAuth0
hook here.
- For example, directly pass in the
- a
getCustomAccessToken
callback that returns the user's access/identity token from your auth provider as astring
. If the user is not authenticated with your auth provider, this callback should returnundefined
.- Pass in the lightweight wrapper (
getCustomToken
) around thegetCredentials
method from Auth0'suseAuth0
hook.
- Pass in the lightweight wrapper (
Why do we need to wrap Auth0's getCredentials
?
Privy must re-request an access/identity token for your user whenever their auth state changes. The wrapper in the code snippet above ensures that the callback passed to getCustomAccessToken
gets recomputed whenever your user's auth state (isAuthenticated
) updates:
tsx
// This is copy-pasted from the code snippet above for visibility
const getCustomToken = useCallback(async () => {
const creds = await getCredentials();
return creds?.idToken;
}, [isLoading, auth0User, getCredentials]);
(2) Wrap your app's screens/components with your custom wrapper of the PrivyProvider
Wrap your app's components/screens with the custom wrapper component (e.g EmbeddedWalletProvider
) we wrote above.
Make sure to appropriately nest this custom component in your applications Root
component. Since EmbeddedWalletProvider
invokes Auth0's useAuth0
hook, it must be nested within Auth0's Auth0Provider
React Context, like below:
tsx
import {Auth0Provider} from 'react-native-auth0';
// Import the custom wrapper component we just wrote
import EmbeddedWalletProvider from './EmbeddedWalletProvider';
function MyApp() {
return (
<>
<Auth0Provider {...insertYourAuth0ProviderProps}>
{/* Our custom wrapper component must be nested inside Auth0Provider */}
<EmbeddedWalletProvider>{...MyAppComponent}</EmbeddedWalletProvider>
</Auth0Provider>
</>
);
}
export default MyApp;
You can now use Privy (e.g. call the usePrivy
and useEmbeddedWallet
hooks from any content wrapped by the EmbeddedWalletProvider
)!
4. Use the embedded wallet!
That's it! You can interface with the user's embedded wallet in any component wrapped by the PrivyProvider
(or your custom wrapper component) to take on-chain actions: