👤 LoginWithPaper
Quickstart
- Create an OAuth Client to get a Client ID in Dashboard: Developers.
- Render the
LoginWithPaper
component. - Pass the Client ID to the
PaperSDKProvider
. - When a user signs in, the
onSuccess
callback is called with acode
. - Exchange the
code
for auserToken
via thePOST /v1/oauth/token
API. - Query the NFTs in the user's wallet with the
userToken
to access NFT-gated content on your app.
Use Cases
- You want to provide a web3 authentication flow for users without a wallet. This flow can complement or replace your existing web3 authentication (e.g. Metamask, WalletConnect).
- You require all authenticated users on your app to have a unique and verifiable wallet address that can hold NFTs.
- You need to verify ownership of tokens in a user's wallet to grant access to NFT-gated content.
Prerequisites
None
This SDK is available in ReactJS.
Integration (ReactJS)
In Dashboard: Developers, create an OAuth client to get a Client ID, a public identifier that associates logins with your account.
On your frontend, render the LoginWithPaper
component. In the onSuccess
callback, call your backend to exchange the expiring code for a permanent user token.
<PaperSDKProvider clientId='MY_CLIENT_ID' chainName='Polygon'>
<LoginWithPaper onSuccess={async (code: string) => {
await fetch('/api/exchange-user-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code }),
});
}}
/>
</PaperSDKProvider>
On your backend, exchange the expiring code for a permanent user token.
const resp = await fetch('https://paper.xyz/api/v1/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer MY_API_SECRET_KEY',
},
body: JSON.stringify({
code: req.body.code,
clientId: 'MY_CLIENT_ID',
}),
});
if (resp.status === 200) {
const { userToken } = await resp.json();
// ...`userToken` is a permanent token used to retrieve user/wallet details.
}
With the userToken
, you can query NFTs in the user's wallet or retrieve user details.
const resp = await fetch('https://paper.xyz/api/v1/nft/token-balance', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer MY_API_SECRET_KEY',
},
body: JSON.stringify({
userToken,
clientId: 'MY_CLIENT_ID',
tokenType: 'erc721',
chainName: 'Polygon',
contractAddress: '0x...',
}),
})
if (resp.status === 200) {
const nftsHeld = await resp.json();
console.log(`You are holding ${nftsHeld.length} of my NFT.`);
}
User flow
The user initially sees a login button.
When clicked a popup is opened to sign in.
Props
Callback Function | Type | Description |
---|---|---|
onSuccess * | (code: string) => void | A callback called when the user successfully verifies their email address and a wallet is created for them. |
onError | (error: PaperSDKError) => void | A callback called if there is an error sending the email or creating a wallet address. |
onClose | () => void | A callback called when the login popup is closed. |
redirectUrl | string | A URL to redirect the user once they click the link in their email. If not provided, the email link prompts the user to close the tab and return to your app. |
Customization
If no child element is provided, a default button is rendered.
Provide your own button by passing a child element into the React component.
<LoginWithPaper onSuccess={onSuccessLogin}>
<button class='my-button'>Sign in with email</button>
</LoginWithPaper>
Updated 21 days ago