Im trying to setup SFA with React Native. When I try to press login it goes to the Auth0 login page. I successfully login. But after I get a 403 error. This is the error:
{
"_bodyBlob": {
"_data": {
"__collector": [Object],
"blobId": "92b4834c-2523-4aa3-8a66-7729fb730aa3",
"offset": 0,
"size": 161
},
"_bodyInit": {
"_data": {
"__collector": [Object],
"blobId": "92b4834c-2523-4aa3-8a66-7729fb730aa3",
"offset": 0,
"size": 161
}
},
"bodyUsed": false
},
"headers": {
"map": {
"content-length": "161",
"content-security-policy": "default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests",
"content-type": "application/json; charset=utf-8",
"cross-origin-opener-policy": "same-origin",
"cross-origin-resource-policy": "same-origin",
"date": "Tue, 26 Mar 2024 21:25:03 GMT",
"etag": "W/\"a1-/mDt6IFe35ttqXMNpfBTzBS1i4Q\"",
"origin-agent-cluster": "?1",
"referrer-policy": "no-referrer",
"strict-transport-security": "max-age=15552000; includeSubDomains",
"vary": "Origin, Accept-Encoding",
"x-content-type-options": "nosniff",
"x-dns-prefetch-control": "off",
"x-download-options": "noopen",
"x-frame-options": "SAMEORIGIN",
"x-permitted-cross-domain-policies": "none",
"x-xss-protection": "0"
}
},
"ok": false,
"status": 403,
"statusText": "",
"type": "default",
"url": "https://signer.web3auth.io/api/allow"
}
This is the code:
import '@ethersproject/shims';
import { decode as atob } from "base-64";
import React, {useEffect, useState} from 'react';
import {
Button,
ScrollView,
StyleSheet,
Text,
View,
Dimensions,
ActivityIndicator,
} from 'react-native';
import {IProvider} from '@web3auth/base';
import Web3Auth from '@web3auth/single-factor-auth-react-native';
import {EthereumPrivateKeyProvider} from '@web3auth/ethereum-provider';
import EncryptedStorage from 'react-native-encrypted-storage';
import { Auth0Provider, useAuth0 } from "react-native-auth0";
import {ethers} from 'ethers';
import { clientIdWeb3, clientIdAuth0, domainAuth0, } from './Config';
const clientId = clientIdWeb3; // get from https://dashboard.web3auth.io
const verifier = 'Auth02';
const chainConfig = {
chainId: '0x1', // Please use 0x1 for Mainnet
rpcTarget: 'https://rpc.ankr.com/eth',
displayName: 'Ethereum Mainnet',
blockExplorer: 'https://etherscan.io/',
ticker: 'ETH',
tickerName: 'Ethereum',
};
const web3auth = new Web3Auth(EncryptedStorage, {
clientId,
web3AuthNetwork: 'sapphire_mainnet',
usePnPKey: false, // By default, this sdk returns CoreKitKey
});
const privateKeyProvider = new EthereumPrivateKeyProvider({
config: {chainConfig},
});
const Home = () => {
const [provider, setProvider] = useState<IProvider | null>(null);
const [loggedIn, setLoggedIn] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(false);
const [userInfo, setUserInfo] = useState<string>('');
const [consoleUI, setConsoleUI] = useState<string>('');
useEffect(() => {
async function init() {
try {
await web3auth.init(privateKeyProvider);
if (web3auth.sessionId) {
setProvider(web3auth.provider);
setLoggedIn(true);
uiConsole('Logged In', web3auth.sessionId);
}
} catch (error) {
uiConsole(error, 'mounted caught');
}
}
init();
}, []);
const { authorize, clearSession, getCredentials } = useAuth0();
const signInWithAuth0 = async (): Promise<string | undefined> => {
try {
// Authorization with Auth0
const credentials: any = await authorize({
domain: domainAuth0,
scope: "openid profile email",
responseType: "token id_token",
customScheme: "com.web3authsfafirebase",
} as any); // Type assertion for bypassing type checks
return credentials.idToken;
} catch (error) {
console.error("Error during Auth0 signIn:", error);
throw new Error("Failed to sign in with Auth0");
}
};
const parseToken = (token: any) => {
try {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace('-', '+').replace('_', '/');
return JSON.parse(atob(base64 || ''));
} catch (err) {
uiConsole(err);
return null;
}
};
const login = async () => {
try {
setConsoleUI("Logging in");
setLoading(true);
const idToken : any = await signInWithAuth0();
uiConsole("idToken", idToken);
const parsedToken = parseToken(idToken);
setUserInfo(parsedToken);
const verifierId = parsedToken.sub;
const provider = await web3auth!.connect({
verifier, // 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,
});
setLoading(false);
if (web3auth.connected) {
setLoggedIn(true);
uiConsole('Logged In');
}
} catch (e) {
uiConsole(e);
setLoading(false);
}
};
const getAccounts = async () => {
setConsoleUI('Getting account');
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(provider!);
// For ethers v5
// const signer = ethersProvider.getSigner();
const signer = await ethersProvider.getSigner();
// Get user's Ethereum public address
const address = signer.getAddress();
uiConsole(address);
};
const getBalance = async () => {
setConsoleUI('Fetching balance');
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(provider!);
// For ethers v5
// const signer = ethersProvider.getSigner();
const signer = await ethersProvider.getSigner();
// Get user's Ethereum public address
const address = signer.getAddress();
// Get 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
);
uiConsole(balance);
};
const signMessage = async () => {
setConsoleUI('Signing message');
// For ethers v5
// const ethersProvider = new ethers.providers.Web3Provider(this.provider);
const ethersProvider = new ethers.BrowserProvider(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);
uiConsole(signedMessage);
};
const logout = async () => {
web3auth.logout();
setProvider(null);
setLoggedIn(false);
setUserInfo('');
};
const uiConsole = (...args: any) => {
setConsoleUI(JSON.stringify(args || {}, null, 2) + '\n\n\n\n' + consoleUI);
console.log(...args);
};
const loggedInView = (
<View style={styles.buttonArea}>
<Button title="Get User Info" onPress={() => uiConsole(userInfo)} />
<Button title="Get Accounts" onPress={() => getAccounts()} />
<Button title="Get Balance" onPress={() => getBalance()} />
<Button title="Sign Message" onPress={() => signMessage()} />
<Button title="Log Out" onPress={logout} />
</View>
);
const unloggedInView = (
<View style={styles.buttonArea}>
<Button title="Login with Web3Auth" onPress={login} />
{loading && <ActivityIndicator />}
</View>
);
return (
<View style={styles.container}>
{loggedIn ? loggedInView : unloggedInView}
<View style={styles.consoleArea}>
<Text style={styles.consoleText}>Console:</Text>
<ScrollView style={styles.consoleUI}>
<Text>{consoleUI}</Text>
</ScrollView>
</View>
</View>
);
}
const App = () => {
return (
<Auth0Provider domain={domainAuth0} clientId={clientIdAuth0}>
<Home />
</Auth0Provider>
);
};
-
SDK Version: “@web3auth/single-factor-auth-react-native”: “^2.1.0”,
-
Platform: react-native
-
Browser Console Screenshots:
- Verifier Name: Auth02
- JWKS Endpoint: Not used(I used email instead of sub in web3auth dashboard)
- Sample idToken (JWT): not used
I have setup a custom authentication inside the Web3Auth dashboard.