Integrate Firebase with Web3Auth SFA React Native SDK
This guide will cover the basics of how to set up your Web3Auth SDK and Firebase account for the integration and provide you with the links on how to develop a basic bare react native application on the blockchain of your choice.
Quick Start
npx degit Web3Auth/web3auth-core-kit-examples/single-factor-auth-react-native/sfa-rn-bare-quick-start sfa-rn-bare-firebase-demo && cd sfa-rn-bare-firebase-demo && npm install && npm run start
How it works?
Single Factor Auth SDKs allow for the integration of a single factor of authentication, such as social login, into your dApp. They are designed to be simple to use and can be integrated into your dApp with minimal effort, allowing you to directly use the Web3Auth Network for Wallet Management. This is one of the most common use cases of Web3Auth, however, it is semi-custodial in nature, since the key is custodial to the Auth Provider and the Web3Auth Network.
- The first step for the application is to get the user authenticated by a login provider(here,
Google) and get the user's
idToken
. - Once the social login is successful, depending on whether the user has enabled Multi-Factor Authentication(MFA) or not, the key is generated.
- If the user has not enabled MFA, we use the
@web3auth/single-factor-auth
SDK to retrieve the private key shares from the Web3Auth auth network nodes and reconstruct the private key. - If the user has enabled MFA, an error message is shown that the user has enabled MFA and in this case, they should be using the Web3Auth Plug and Play Web SDKs.
Prerequisites
-
For Web Apps: A basic knowledge of JavaScript is required to use Web3Auth SDK.
-
For Mobile Apps: For the Web3Auth Mobile SDKs, you have a choice between iOS, Android, React Native & Flutter. Please refer to the Web3Auth SDK Reference for more information.
-
Create a Web3Auth account on the Web3Auth Dashboard
-
A Firebase account to be used as a Federated Identity Provider.
-
A Google Developer account to be used as an Identity provider for Firebase.
Setup
Setup Firebase
- Go to your Firebase console and create a Web App. Follow this guide on how to set up your Firebase Web App project.
Create a Firebase Project
-
Create a new project by clicking on Add project or use your existing project from Firebase console.
-
Give your project a name and click on Continue
-
Finally, click on Create Project
Select Authentication Provider
-
Once the project is created. Set up authentication by clicking on the Authentication card from the home screen of your project or choose Authentication under Build from the left sidebar.
-
From the Sign-in method tab, select any provider you wish to enable. For this guide, we'll be enabling Google.
-
Finally, toggle the enable button and click on Save
Configure Firebase for React Native
Please follow the guide here to configure Firebase for React Native.
Setup Web3Auth
Setup Web3Auth Project
-
Create a Project from the Project Section of the Web3Auth Developer Dashboard.
-
Enter your desired Project name.
-
Select the Product you want to use. For this guide, we'll be using the Plug n Play product.
-
Select the Platform type you want to use. For this guide, we'll be using the Web Application as the platform.
-
Select the Web3Auth Network as
Sapphire Devnet
. We recommend creating a project in thesapphire_devnet
network during development. While moving to a production environment, make sure to convert your project tosapphire_mainnet
or any of the legacy mainnet networkmainnet
,aqua
, orcyan
network. Otherwise, you'll end up losing users and keys. -
Select the blockchain(s) you'll be building this project on. For interoperability with Torus Wallets, you have the option of allowing the user's private key to be used in other applications using Torus Wallets (EVM, Solana, XRPL & Casper).
-
Finally, once you create the project, you have the option to whitelist your URLs for the project. Please whitelist the domains where your project will be hosted.
-
Setup Firebase Custom Authentication Verifier
Create a Firebase Verifier from the Custom Authentication tab of your Web3Auth Project.
-
Click on the
Custom Authentication
tab of your Web3Auth Project. -
Click on the
Create Verifier
button. -
Enter a name of your choice for the verifier identifier.
eg. w3a-firebase-demo
-
Select
Custom Providers
from the Choose a Login Provider section. -
JWKS Endpoint: Enter
https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com
as the JWKS endpoint for the Firebase. -
Now you have the option to paste a sample idToken(JWT) to get the fields for the JWT validation. This step is optional, but if you have a sample JWT you can paste it here to get the fields for the JWT validation. You can also skip this step and fill in the fields manually.
-
The following are the JWT validation fields needed for the Firebase JWT validation:
- Type
iss
as a field andhttps://securetoken.google.com/FIREBASE-PROJECT-ID
as a value. - Next, type
aud
as a field andFIREBASE-PROJECT-ID
as a value.
Note: Replace the
FIREBASE-PROJECT-ID
with your Firebase Project ID. - Type
-
Next, Select
Sub
,Email
or aCustom
value from the dropdown for the JWT Verifier ID. This is the field that will be used as the verifier ID for the user, and it has to be unique for each user. -
Finally, Click on the
Create
button to create your verifier.
It may take up to 10 minutes to deploy the verifier on sapphire_devnet. You'll receive an email once it's complete.
Using the Web3Auth SFA Web SDK
To use the Web3Auth SFA Web SDK, you need to add @web3auth/single-factor-auth-react-native
to your
project.
Installation
For this project, you need to add the following Web3Auth dependencies to your package.json
npm install --save @web3auth/single-factor-auth-react-native @web3auth/ethereum-provider ethers @react-native-firebase/app @react-native-firebase/auth react-native-encrypted-storage
Understanding the Dependencies
@web3auth/ethereum-provider
This package is used to provide the Ethereum provider to the Web3Auth SDK. This is required to interact with the blockchain.
npm install --save @web3auth/ethereum-provider
@web3auth/single-factor-auth-react-native
This package is the core package for Single Factor Auth React Native SDK.
npm install --save @web3auth/single-factor-auth-react-native
ethers
This package is used to interact with the blockchain.
npm install --save ethers
@react-native-firebase/app
& @react-native-firebase/auth
This package is used to interact with the Firebase SDK.
npm install --save @react-native-firebase/app @react-native-firebase/auth
react-native-encrypted-storage
This package is used to store the user's encrypted private key in the device's storage.
npm install --save react-native-encrypted-storage
Initialization
Once installed, your Web3Auth application needs to be initialized. Initialization is a multi-step process where we add all the config details for Web3Auth SDK:
Importing the packages
import "@ethersproject/shims";
import auth from "@react-native-firebase/auth";
import EncryptedStorage from "react-native-encrypted-storage";
import Web3Auth from "@web3auth/single-factor-auth-react-native";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { ethers } from "ethers";
Instantiate the Web3Auth SFA React Native SDK
import "@ethersproject/shims";
import auth from "@react-native-firebase/auth";
import EncryptedStorage from "react-native-encrypted-storage";
import Web3Auth from "@web3auth/single-factor-auth-react-native";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { ethers } from "ethers";
const clientId =
"BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ"; // get from https://dashboard.web3auth.io
const chainConfig = {
chainId: "0x1",
displayName: "Ethereum Mainnet",
chainNamespace: CHAIN_NAMESPACES.EIP155,
tickerName: "Ethereum",
ticker: "ETH",
decimals: 18,
rpcTarget: "https://rpc.ankr.com/eth",
blockExplorer: "https://etherscan.io",
};
// Initializing Web3Auth SDK
const web3auth = new Web3Auth(EncryptedStorage, {
clientId, // Get your Client ID from Web3Auth Dashboard
web3AuthNetwork: "sapphire_mainnet",
});
// Initializing Ethereum Provider
const privateKeyProvider = new EthereumPrivateKeyProvider({
config: { chainConfig },
});
Here, we're using the chainConfig
property to set the chainId
and chainNamespace
among other
parameters. The chainId
and chainNamespace
are the id and the namespace respectively of the
chain you're connecting to. We've initialized them for EVM for this guide. You can find the list of
available providers here to select from.
Additionally, sometimes you might face clogging in the network because the test network is a bit
clogged at that point. To avoid this, we can use the property rpcTarget
and pass over the URL of
the node you want to connect to.
Initializing the Web3Auth SDK
await web3auth.init(privateKeyProvider);
Authentication
Getting the idToken
and initializing Web3Auth
import { safeatob } from "@toruslabs/openlogin-utils";
async function signInWithEmailPassword() {
try {
const res = await auth().signInWithEmailAndPassword("custom+jwt@firebase.login", "Testing@123");
return res;
} catch (error) {
console.error(error);
}
}
const parseToken = (token: any) => {
try {
const payload = token.split(".")[1]; // payload
return JSON.parse(safeatob(payload));
} catch (err) {
console.log(err);
return null;
}
};
const login = async () => {
try {
const loginRes = await signInWithEmailPassword();
const idToken = await loginRes!.user.getIdToken(true);
const parsedToken = parseToken(idToken);
const verifierId = parsedToken.sub;
await web3auth!.connect({
verifier: "w3a-firebase-demo", // e.g. `web3auth-sfa-verifier` replace with your verifier name, and it has to be on the same network passed in init().
verifierId, // e.g. `Yux1873xnibdui` or `name@email.com` replace with your verifier id(sub or email)'s value.
idToken,
});
if (web3auth.connected) {
console.log("Logged In");
}
} catch (e) {
console.log(e);
}
};
Here, we're using the parseToken
function to parse the idToken
and get the sub
property from
it. The sub
property is the unique identifier of the user.
Please refer to our example if you need help with handling the session with React.
Since we are directly using Single Factor Auth SDK to log in, the Web3Auth getUserInfo
function
won't work. We need to get the user details directly from the idToken
.
Get the User Profile
import { safeatob } from "@toruslabs/openlogin-utils";
const parseToken = (token: any) => {
try {
const token = token.split(".")[1]; // payload
return JSON.parse(safeatob(token));
} catch (err) {
console.error(err);
return null;
}
};
const userProfile = parseToken(idToken);
Logout
Logging out your user is as simple as calling the logout
function on the Web3Auth SDK.
await web3auth.logout();
Interacting with the Blockchain
So if you have completed this far, it means that you have successfully authenticated your user. Now,
you can use the provider returned by Web3Auth as web3auth.provider
to interact with your
blockchain. You can use the Provider SDKs to perform RPC Calls to your
blockchain.
Web3Auth is chain agnostic, ie. depending on whatever blockchain or layer-2 you use, Web3Auth can
easily support that. Web3Auth has native providers for EVM and Solana blockchains and for others,
you can get the private key in the user scope and make RPC calls. For standardising the type of
provider, Web3Auth Base provides a IProvider
from which you can create your own provider.
- Ethereum Provider gives you the capability of making RPC calls to the EVM compatible blockchains.
- Solana Provider gives you the capability of making RPC calls to the Solana blockchain.
- XRPL Provider gives you the capability of making RPC calls to the XRPL blockchain.
- If you want to use any other chain except Solana or EVM chains, for ex: Starknet, you can specify
the value of
chainNamespace
field as other in the Web3Auth SDK Constructor. Refer to: Using other blockchains
Get User Accounts
- Web3
- Ethers.js
const getAccounts = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const web3 = new Web3(provider as any);
const userAccounts = await web3.eth.getAccounts();
console.log(userAccounts);
};
const getAccounts = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(this.provider);
// For ethers v5
// const signer = ethersProvider.getSigner();
const signer = await ethersProvider.getSigner();
// Get the user's Ethereum public address
const address = signer.getAddress();
console.log(address);
};
View User Balance
- Web3
- Ethers.js
const getBalance = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const web3 = new Web3(provider as any);
const accounts = await web3.eth.getAccounts();
const balance = await web3.eth.getBalance(accounts[0]);
console.log(web3.utils.fromWei(balance));
};
const getBalance = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(this.provider);
// For ethers v5
// const signer = ethersProvider.getSigner();
const signer = await ethersProvider.getSigner();
// Get the user's Ethereum public address
const address = signer.getAddress();
// Get the user's balance in ether
// For ethers v5
// const balance = ethers.utils.formatEther(
// await ethersProvider.getBalance(address) // Balance is in wei
// );
const balance = ethers.formatEther(
await ethersProvider.getBalance(address), // Balance is in wei
);
console.log(balance);
};
Sign Message
- Web3
- Ethers.js
const signMessage = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const web3 = new Web3(provider as any);
// Get user's Ethereum public address
const account = (await web3.eth.getAccounts())[0];
// Message
const message = "Hello MPC, Bye Bye SeedPhrase";
const typedMessage = [
{
type: "string",
name: "message",
value: message,
},
];
const params = [JSON.stringify(typedMessage), account];
const method = "eth_signTypedData";
const signedMessage = await this.provider.request({
method,
params,
});
console.log(signedMessage);
};
const signMessage = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(this.provider);
// For ethers v5
// const signer = ethersProvider.getSigner();
const signer = await ethersProvider.getSigner();
const originalMessage = "YOUR_MESSAGE";
// Sign the message
const signedMessage = await signer.signMessage(originalMessage);
console.log(signedMessage);
};
Sign Transaction
const signTransaction = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const web3 = new Web3(provider as any);
const accounts = await web3.eth.getAccounts();
const txRes = await web3.eth.signTransaction({
from: accounts[0],
to: accounts[0],
value: web3.utils.toWei("0.0001"),
chainId: 1, // change it to your specific chain id.
});
console.log(txRes.transactionHash);
};
Send Transaction
- Web3
- Ethers.js
const sendTransaction = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
const web3 = new Web3(provider as any);
const accounts = await web3.eth.getAccounts();
const txRes = await web3.eth.sendTransaction({
from: accounts[0],
to: accounts[0],
value: web3.utils.toWei("0.0001"),
chainId: 1, // change it to your specific chain id.
});
console.log(txRes.transactionHash);
};
const sendTransaction = async () => {
if (!provider) {
console.log("provider not initialized yet");
return;
}
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(this.provider);
// For ethers v5
// const signer = ethersProvider.getSigner();
const signer = await ethersProvider.getSigner();
const destination = "0x40e1c367Eca34250cAF1bc8330E9EddfD403fC56";
// Convert 1 ether to wei
// For ethers v5
// const amount = ethers.utils.parseEther("0.001");
const amount = ethers.parseEther("0.001");
// Submit transaction to the blockchain
const tx = await signer.sendTransaction({
to: destination,
value: amount,
maxPriorityFeePerGas: "5000000000", // Max priority fee per gas
maxFeePerGas: "6000000000000", // Max fee per gas
});
// Wait for the transaction to be mined
const receipt = await tx.wait();
console.log(receipt.transactionHash);
};
Example Code
The code for the example can be found here.
Troubleshooting
Please refer to the React Native Troubleshooting Guide if you face any hurdles.
Questions?
Ask us on Web3Auth Community Portal.