Appearance
Callbacks
Callbacks allow your app to execute arbitrary logic after a Privy method completes.
As examples:
- After a user logs in, you might want to execute a CAPTCHA test to verify that they are human.
- After a user connects a wallet, you might want to prompt them to switch to a specific network.
- After a user logs out, you might want to log an analytics event in your backend.
You can accomplish all of the above, and more, with callbacks! Read below to learn more.
TIP
Whenever an event (such as a login, wallet creation, etc.) is detected, every callback specified for that event across all currently mounted components will be triggered. Thus, if you define and mount multiple callback hooks on the same page, all callbacks will trigger whenever the event success/failure is detected. Please ensure that you are not unintentionally mounting duplicate hooks when defining callbacks in your application.
useLogin
To configure callbacks for Privy's login
method, use the useLogin
hook:
tsx
import {useLogin} from '@privy-io/react-auth';
const {login} = useLogin({
onComplete: (user, isNewUser, wasAlreadyAuthenticated, loginMethod, linkedAccount) => {
console.log(user, isNewUser, wasAlreadyAuthenticated, loginMethod, linkedAccount);
// Any logic you'd like to execute if the user is/becomes authenticated while this
// component is mounted
},
onError: (error) => {
console.log(error);
// Any logic you'd like to execute after a user exits the login flow or there is an error
},
});
// Then call `login` in your code, which will invoke these callbacks on completion
As parameters to useLogin
, you may include an onComplete
callback and/or an onError
callback.
onComplete
If set, the behavior of onComplete
depends on if the user is already authenticated
or not when the component is mounted to the page. Specifically:
- If the user is already
authenticated
when the component is mounted, the callback will execute immediately, as soon as the component mounts. - If the user is not
authenticated
when the component is mounted, the callback will execute only after the user completes a successfullogin
attempt and becomesauthenticated
.
Within this callback, you can access:
user
: the user object with the user's DID, linked accounts, and moreisNewUser
: a boolean indicating if this is the user's first login or if they are a returning userwasAlreadyAuthenticated
: a boolean indicating if the user was alreadyauthenticated
when the component was mounted (case 1 from above) or if they becameauthenticated
during this component's lifecycle (case 2 from above)loginMethod
: a string indicating the authentication method used if the user just logged in, ornull
if the userwasAlreadyAuthenticated
when this component mounted.- Possible
loginMethod
s are'email'
,'sms'
,'siwe'
(external wallet),'apple'
,'discord'
,'github'
,'google'
,'linkedin'
,'spotify'
,'tiktok'
, and'twitter'
.
- Possible
linkedAccount
: an object representing the account that the user just used to authenticate into the app with.- The
linkedAccount
will be an object whosetype
value will be one of'wallet'
,'email'
,'phone'
,'google_oauth'
,'twitter_oauth'
,'discord_oauth'
,'github_oauth'
,'spotify_oauth'
,'instagram_oauth'
,'tiktok_oauth'
,'linkedin_oauth'
,'apple_oauth'
,'custom_auth'
,'farcaster'
, or'passkey'
.
- The
You can use the onComplete
callback to invoke arbitrary logic for already-authenticated
users and/or un-authenticated
users who will login
.
See an example of using the onComplete callback for login!
As an example, you might configure an onComplete
callback to support the following behavior:
- If the user
wasAlreadyAuthenticated
, redirect them away from your landing page to their profile page. - If the user logs in, and
isNewUser
, create the user in your own Users DB. - If the user logs in, and is a returning user, fetch their data from your own Users DB.
Below is a template for implementing the above with onComplete
:
tsx
const onComplete = (user, isNewUser, wasAlreadyAuthenticated, loginMethod, linkedAccount) => {
if (wasAlreadyAuthenticated) {
// In this case, the user was already `authenticated` when this component was mounted.
//
// For already-`authenticated` users, we redirect them to their profile page.
router.push('/profile');
} else {
// In this case, the user was not already `authenticated` when the component was mounted
// but successfully complete `login` during this component's lifecycle.
//
// For new `login`s, we make an API request to our backend to find or create the user in our
// own DBs.
if (isNewUser) {
// If the user is new, create it in your backend
await fetch('your-create-user-endpoint', {
method: 'POST',
body: JSON.stringify(user),
...
});
} else {
// If the user is returning, fetch their data from your backend
await fetch(`your-find-user-endpoint/${user.id}`, {
method: 'GET',
...
});
}
}
}
TIP
For redirects on login, we recommend using router.replace
instead of window.location.replace
to avoid a full page refresh where possible. This ensures that processes still occurring in memory (embedded wallet creation, processing of OAuth query parameters, and more) are not disrupted by the redirect.
onError
If set, the onError
callback will execute after a user initiates a login attempt and there is an error, or if the user exits the login flow prematurely. Within this callback, you may access an error
code with more information about the error.
useLinkAccount
To configure callbacks for Privy's link
methods, use the useLinkAccount
hook:
tsx
import {useLinkAccount} from '@privy-io/react-auth';
// can return any of the `link____` methods in the callback below
const {linkGoogle, linkEmail} = useLinkAccount({
onSuccess: (user, linkMethod, linkedAccount) => {
console.log(user, linkMethod, linkedAccount);
// Any logic you'd like to execute if the user successfully links an account while this
// component is mounted
},
onError: (error, details) => {
console.log(error, details);
// Any logic you'd like to execute after a user exits the link flow or there is an error
},
});
// Then call one of the `link` methods in your code, which will invoke these callbacks on completion
As parameters to useLinkAccount
, you may include an onSuccess
callback and/or an onError
callback. Note that these callbacks will trigger whenever any new account is linked to a Privy user.
onSuccess
If set, the onSuccess
callback will execute after a user has successfully links any type of new login method to their Privy account.
Within this callback, you can access:
user
: the user object with the user's DID, linked accounts, and more mounted (case 1 from above) or if they becameauthenticated
during this component's lifecycle (case 2 from above)linkMethod
: a string indicating the type of link flow just executed for the authenticated user.- Possible
linkMethods
s are'email'
,'sms'
,'siwe'
(external wallet),'apple'
,'discord'
,'github'
,'google'
,'linkedin'
,'spotify'
,'tiktok'
, and'twitter'
.
- Possible
linkedAccount
: an object representing the account that was just linked to the authenticated user.- The
linkedAccount
will be an object whosetype
value will be one of'wallet'
,'email'
,'phone'
,'google_oauth'
,'twitter_oauth'
,'discord_oauth'
,'github_oauth'
,'spotify_oauth'
,'instagram_oauth'
,'tiktok_oauth'
,'linkedin_oauth'
,'apple_oauth'
,'custom_auth'
,'farcaster'
, or'passkey'
.
- The
You can use the onSuccess
callback to invoke arbitrary logic for users successfully adding a linkedAccount
.
See an example of using the onSuccess callback for linking an account!
As an example, you might configure an onSuccess
callback to support the following behavior:
- If the user links an email to their account, add an email or phone number to your own Users DB.
Below is a template for implementing the above with onSuccess
:
tsx
const onSuccess = (user, linkedAccountMethod) => {
if (linkedAccountMethod === 'email') {
// If the user is new, create it in your backend
await fetch('your-add-email-to-user-endpoint', {
method: 'POST',
body: JSON.stringify(user),
...
}
} else if (linkedAccountMethod === 'sms') {
// If the user is returning, fetch their data from your backend
await fetch('your-add-phone-number-to-user-endpoint', {
method: 'POST',
body: JSON.stringify(user),
...
}
}
}
onError
If set, the onError
callback will execute after a user initiates a link attempt and there is an error, or if the user exits the link flow prematurely. Within this callback, you can access:
error
: the error code with more information about the error.details.linkMethod
: a string indicating the type of link flow just attempted for the authenticated user.
useConnectWallet
To configure callbacks for Privy's connectWallet
method, use the useConnectWallet
hook:
tsx
import {useConnectWallet} from '@privy-io/react-auth';
const {connectWallet} = useConnectWallet({
onSuccess: (wallet) => {
console.log(wallet);
// Any logic you'd like to execute after a user successfully connects their wallet
},
onError: (error) => {
console.log(error);
// Any logic you'd like to execute after a user exits the connection flow or there is an error
},
});
// Then call `connectWallet` in your code, which will invoke these callbacks on completion
As parameters to useConnectWallet
, you may include an onSuccess
callback and/or an onError
callback.
While this component is mounted, any invocation of connectWallet
will trigger the onSuccess
callback or onError
callback on completion, depending on if the connection attempt was successful or not.
When calling connectWallet
you can also pass in an optional options
param with suggestedAddress
to suggest a wallet address for the user to connect.
tsx
const {connectWallet} = useConnectWallet();
connectWallet({
suggestedAddress: '0x1234567890abcdef1234567890abcdef12345678',
});
onSuccess
If set, the onSuccess
callback will execute after a user has successfully connected their wallet to your app. Within this callback, you can access a wallet
parameter, which is the ConnectedWallet
object for the wallet that the user has just connected.
onError
If set, the onError
callback will execute after a user initiates a connection attempt and there is an error, or if the user exits the connection flow prematurely. Within this callback, you may access an error
code with more information about the error.
useCreateWallet
To configure callbacks for Privy's createWallet
method, use the useCreateWallet
hook:
tsx
import {useCreateWallet} from '@privy-io/react-auth';
const {createWallet} = useCreateWallet({
onSuccess: (wallet) => {
console.log(wallet);
// Any logic you'd like to execute after a user successfully creates their wallet
},
onError: (error) => {
console.log(error);
// Any logic you'd like to execute after a user exits the creation flow or there is an error
},
});
// Then call `createWallet` in your code, which will invoke these callbacks on completion
As parameters to useCreateWallet
, you may include an onSuccess
callback and/or an onError
callback.
While this component is mounted, any invocation of createWallet
will trigger the onSuccess
callback or onError
callback on completion, depending on if the connection attempt was successful or not.
onSuccess
If set, the onSuccess
callback will execute after a user has successfully created their wallet. Within this callback, you can access a wallet
parameter, which is the Wallet
object for the wallet that the user has just created.
onError
If set, the onError
callback will execute after a user initiates a connection attempt and there is an error, or if the user exits the creation flow prematurely. Within this callback, you may access an error
code with more information about the error.
useSetWalletPassword
To configure callbacks for Privy's setWalletPassword
method, use the useSetWalletPassword
hook:
tsx
import {useSetWalletPassword} from '@privy-io/react-auth';
const {setWalletPassword} = useSetWalletPassword({
onSuccess: (wallet) => {
console.log(wallet);
// Any logic you'd like to execute after a user successfully sets a password on their wallet
},
onError: (error) => {
console.log(error);
// Any logic you'd like to execute after a user exits the password-setting flow or there is an error
},
});
// Then call `setWalletPassword` in your code, which will invoke these callbacks on completion
As parameters to useSetWalletPassword
, you may include an onSuccess
callback and/or an onError
callback.
While this component is mounted, any invocation of setWalletPassword
will trigger the onSuccess
callback or onError
callback on completion, depending on if a password was successfully set on an embedded wallet or not.
onSuccess
If set, the onSuccess
callback will execute after a user has successfully sets a password on their wallet. Within this callback, you can access a wallet
parameter, which is the Wallet
object for the wallet that the user has just created.
onError
If set, the onError
callback will execute after a user attempts to set a password and there is an error, or if the user exits the creation flow prematurely. Within this callback, you may access an error
code with more information about the error.
TIP
The onSuccess
callback will fire only when a password is explicitly set using createWallet
. Creating an embedded wallet password via wallet pregeneration or via createOnLogin
will not fire this callback.
useLogout
To configure callbacks for Privy's logout
method, use the useLogout
hook:
tsx
import {useLogout} from '@privy-io/react-auth';
const {logout} = useLogout({
onSuccess: () => {
console.log('User logged out');
// Any logic you'd like to execute after a user successfully logs out
},
});
// Then call `logout` in your code, which will invoke this callback on completion
As a parameter to useLogout
, you may include an onSuccess
callback.
While this component is mounted, any successful invocation of logout
will trigger the onSuccess
callback on completion.
onSuccess
If set, the onSuccess
callback will execute after a user successfully logs out from your app. A successful logout requires that the users auth tokens are cleared from their browser, and that their session is terminated in Privy's API.
useModalStatus
To attach a callback to whenever the Privy modal is opened or closed, use the useModalStatus
hook:
tsx
import {useModalStatus} from '@privy-io/react-auth';
const {isOpen} = useModalStatus();
useModalStatus
returns a boolean isOpen
that indicates whether the Privy modal is currently opened or closed within your app's page.
You can then invoke arbitrary logic whenever the user opens or closes the Privy modal by listening to the isOpen
variable in a dependency array, like so:
tsx
const {isOpen} = useModalStatus();
useEffect(() => {
if (isOpen) {
// Replace this with the logic you'd like to run when the modal is opened
console.log('Privy modal is open');
} else {
// Replace this with the logic you'd like to run when the modal is closed
console.log('Privy modal is closed');
}
}, [isOpen]);
useToken
To configure callbacks for whenever Privy updates a user's app access token, use the useToken
hook:
tsx
import {useToken} from '@privy-io/react-auth';
const {getAccessToken} = useToken({
onAccessTokenGranted: (accessToken: string) => {
// Any logic you'd like to execute after Privy has granted a user an app
// access token or has refreshed their existing token
},
onAccessTokenRevoked: () => {
// Any logic you'd like to execute when Privy revokes a user's app access token
// and removes it from cookies or local storage
},
});
// You may also call `getAccessToken` to get the user's current access token
As parameters to useToken
, you may include an onAccessTokenGranted
callback and/or an onAccessTokenRevoked
callback.
TIP
The component where the useToken
hook is invoked must be mounted while Privy grants or revokes the user's app access token in order for these callbacks to execute.
onAccessTokenGranted
If set, the onAccessTokenGranted
callback will execute after Privy grants a new app access token for the user. This happens in two cases:
- An unauthenticated user logs in, becomes authenticated, and receives an app access token to begin their session.
- An authenticated user has their app access token refreshed by Privy.
Within this callback, you can access a accessToken
parameter, which is the access token granted by Privy as a string.
Please note that this callback will execute whenever Privy grants a user a new app access token, and is not tied to any method call. In particular, calling getAccessToken
will only invoke this callback if the user's existing access token must be refreshed, and Privy grants a new one.
onAccessTokenRevoked
If set, the onAccessTokenRevoked
callback will execute after Privy logs out a user and removes their app access token from their browser local storage or cookies.
Please note that this callback will not execute if the user manually deletes their access token from their browser storage or cookies, outside of a Privy flow.
useSignMessage
To configure callbacks for Privy's signMessage
method, use the useSignMessage
hook:
tsx
import {useSignMessage} from '@privy-io/react-auth';
const {signMessage} = useSignMessage({
onSuccess: (signature) => {
console.log(signature);
// Any logic you'd like to execute after a user successfully signs a message
},
onError: (error) => {
console.log(error);
// Any logic you'd like to execute after a user exits the message signing flow or there is an error
},
});
// Then call `signMessage` in your code, which will invoke these callbacks on completion
As parameters to useSignMessage
, you may include an onSuccess
callback and/or an onError
callback.
While this component is mounted, any invocation of signMessage
will trigger the onSuccess
callback or onError
callback on completion, depending on if the message was successfully signed or not.
onSuccess
If set, the onSuccess
callback will execute after a user has successfully signed the message. Within this callback, you can access a signature
parameter, which is the signature
string value generated by the wallet to sign the message.
onError
If set, the onError
callback will execute after a user attempts to sign a message and there is an error, or if the user exits the signature flow prematurely. Within this callback, you may access an error
code with more information about the error.
useSignTypedData
To configure callbacks for Privy's signTypedData
method, use the useSignTypedData
hook:
tsx
import {useSignTypedData} from '@privy-io/react-auth';
const {signTypedData} = useSignTypedData({
onSuccess: (signature) => {
console.log(signature);
// Any logic you'd like to execute after a user successfully signs the EIP-712 typed data
},
onError: (error) => {
console.log(error);
// Any logic you'd like to execute after a user exits the signing flow or there is an error
},
});
// Then call `signTypedData` in your code, which will invoke these callbacks on completion
As parameters to useSignTypedData
, you may include an onSuccess
callback and/or an onError
callback.
While this component is mounted, any invocation of signTypedData
will trigger the onSuccess
callback or onError
callback on completion, depending on if the data was successfully signed or not.
onSuccess
If set, the onSuccess
callback will execute after a user has successfully signed the message. Within this callback, you can access a signature
parameter, which is the signature
string value generated by the wallet to sign the data.
onError
If set, the onError
callback will execute after a user attempts to sign the typed data and there is an error, or if the user exits the signature flow prematurely. Within this callback, you may access an error
code with more information about the error.
useSendTransaction
To configure callbacks for Privy's sendTransaction
method, use the useSendTransaction
hook:
tsx
import {useSendTransaction} from '@privy-io/react-auth';
const {sendTransaction} = useSendTransaction({
onSuccess: (response) => {
console.log(response);
// Any logic you'd like to execute after a user successfully sends a transaction
},
onError: (error) => {
console.log(error);
// Any logic you'd like to execute after a user fails to send a transaction
},
});
// Then call `sendTransaction` in your code, which will invoke these callbacks on completion
As parameters to useSendTransaction
, you may include an onSuccess
callback and/or an onError
callback.
While this component is mounted, any invocation of createWallet
will trigger the onSuccess
callback or onError
callback on completion, depending on if the connection attempt was successful or not.
onSuccess
If set, the onSuccess
callback will execute after a user has successfully created their wallet. Within this callback, you can access a response
parameter, which is the response
object of type TransactionResponse for the transaction that the embedded wallet just sent.
onError
If set, the onError
callback will execute after a user initiates a transaction send attempt and there is an error, or if the user exits the transaction flow prematurely. Within this callback, you may access an error
code with more information about the error.
useOAuthTokens
To configure callbacks for whenever a user successfully authorizes a third-party OAuth account, use the useOAuthTokens
hook:
tsx
import {useOAuthTokens, type OAuthTokens} from '@privy-io/react-auth';
const {reauthorize} = useOAuthTokens({
onOAuthTokenGrant: (tokens: OAuthTokens, {user}: {user: User}) => {
// Any logic you'd like to execute after Privy has granted a user an app
// access token or has refreshed their existing token
api.push({accessToken: tokens.accessToken, refreshToken: tokens.refreshToken, userId: user.id});
},
});
// You may also call `getAccessToken` to get the user's current access token
As parameters to useOAuthTokens
, you may include an onOAuthTokenGrant
callback.
TIP
The component where the useOAuthTokens
hook is invoked must be mounted on the component/page the user returns to after authorizing an OAuth flow in order for this callback to execute.
onAccessTokenGranted
If set, the onOAuthTokenGrant
callback will execute after a user returns to the application from an OAuth flow authorization. This happens in 3 cases:
- When the user logs in via an OAuth/social login method,
- When a user links a new OAuth account to their user account,
- When a successful
reauthorize
call is invoked, and the user authorizes an existing OAuth account.
Within this callback, you can access:
provider
: the OAuth provider, is one of'apple'
,'discord'
,'github'
,'google'
,'linkedin'
,'spotify'
,'tiktok'
,'instagram'
, and'twitter'
.accessToken
: the OAuth access tokenaccessTokenExpiresInSeconds
: the number of seconds until the OAuth access token expiresrefreshToken
: the OAuth refresh tokenrefreshTokenExpiresInSeconds
: the number of seconds until the OAuth refresh token expires. If the refresh token is present and this field is undefined, it is assumed that the refresh token does not have an expiration datescopes
: the list of OAuth scopes the access token is approved for.
Learn more about how to use OAuth access and refresh tokens here.
Within this callback, you can also access a reauthorize
method, which will allow a user to re-authorize an existing OAuth account in order to retrieve more up-to-date OAuth tokens and account metadata.
useCustomAuth
INFO
This hook should only be used if you are using Privy with a custom auth provider. Follow these instructions if you wish to use Privy with a custom auth provider!
To configure a callback for whenever Privy synchronizes a user's embedded wallet session with their authenticated session from the provider, use the useCustomAuth
hook:
tsx
import {useCustomAuth} from '@privy-io/react-auth';
const {status} = useCustomAuth({
onAuthenticated: ({user}: {user: User}) => {
// Any logic you'd like to execute after Privy has received a valid custom auth access token
// and authenticates the user
},
onUnauthenticated: () => {
// Any logic you'd like to execute when Privy revokes a user's access token
// after detecting they've logged out in the custom auth provider
},
});
// You may also inspect `status` to get the user's authentication flow state in Privy
As parameters to useCustomAuth
, you may include an onAuthenticated
callback and/or an onUnauthenticated
callback.
onAuthenticated
If set, the onAuthenticated
callback will execute after Privy authenticates a user in Privy after receiving a valid access token from the custom auth provider.
Within this callback, you can access user
: the user object with the user's DID, embedded wallet, and more.
onUnauthenticated
If set, the onUnauthenticated
callback will execute after Privy detects that a user is logged out of your app's custom auth provider, and correspondingly revokes their authentication status and access to their embedded wallet in Privy.
Status
Within this hook, you can also access a status
parameter, which indicates whether Privy's authentication state has synchronized with the custom auth provider state. The possible values of status
are:
{status: 'not-enabled'}
: Custom auth is not enabled for the app{status: 'initial'}
: Privy has not yet synchronized with your app's custom auth provider.{status: 'loading'}
: Privy is synchronizing with your custom auth provider.{status: 'done'}
:: Privy has finished synchronizing with your custom auth provider. Theauthenticated
value fromusePrivy
should now match whether the user is authenticated with your custom provider or not.{status: 'error', error: Error | null}
: There was an error while trying to synchronize the user's authentication state
useSendSolanaTransaction
To configure callbacks for Privy's sendSolanaTransaction
method, use the useSendSolanaTransaction
hook:
tsx
import {useSendSolanaTransaction} from '@privy-io/react-auth';
const {sendSolanaTransaction} = useSendSolanaTransaction({
onSuccess: (response) => {
console.log(response);
// Any logic you'd like to execute after a user successfully sends a transaction
},
onError: (error) => {
console.log(error);
// Any logic you'd like to execute after a user fails to send a transaction
},
});
// Then call `sendSolanaTransaction` in your code, which will invoke these callbacks on completion
As parameters to useSendSolanaTransaction
, you may include an onSuccess
callback and/or an onError
callback.
While this component is mounted, any invocation of sendSolanaTransaction
will trigger the onSuccess
callback or onError
callback on completion, depending on if the transaction attempt was successful or not.
onSuccess
If set, the onSuccess
callback will execute after the transaction has been sent and confirmed successfully. Within this callback, you can access a response
parameter, which is the response
object of type SolanaTransactionReceipt for the transaction that the embedded wallet just sent.
onError
If set, the onError
callback will execute after a user initiates a transaction send attempt and there is an error, or if the user exits the transaction flow prematurely. Within this callback, you may access an error
code with more information about the error.