Skip to main content

Implement Sign In with Farcaster with Web3Auth SFA JS SDK

single factor authwebfarcasterevmnext.jsWeb3Auth Team | May 6, 2024

Prerequisites:

  • Basic understanding of React and Next.js
  • Familiarity with JavaScript and TypeScript
  • Basic knowledge of authentication and JWT tokens

Step 1: Install and Configure Sign In with Farcaster

a. Install Dependencies: Install auth-kit and its peer dependency viem using npm.

npm install @farcaster/auth-kit viem

Note: auth-kit is a React library. If you're using a different framework, take a look at the client library instead.

b. Import Libraries: Import auth-kit and its CSS styles into your React component.

import "@farcaster/auth-kit/styles.css";
import { AuthKitProvider, SignInButton, useProfile } from "@farcaster/auth-kit";

c. Configure Provider: Set up a provider with your desired configuration including the RPC URL, domain, and login URL.

const config = {
rpcUrl: "https://mainnet.optimism.io",
domain: "example.com",
siweUri: "https://example.com/login",
};

d. Integrate Sign-In Button: Render the SignInButton component in your UI to prompt users to sign in.

const App = () => {
return (
<AuthKitProvider config={config}>
{/* Your App */}
<SignInButton />
</AuthKitProvider>
);
};

Step 2: Verify Signatures on Backend

We will be using NextAuth to implement Authorization logic.

a. Create a NextAuth API: Create an API route using NextAuth to handle authentication and signature verification.

pages/api/auth/[...nextauth].ts

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { createAppClient, viemConnector } from "@farcaster/auth-client";

b. Authorization Logic: Implement authorization logic to verify user signatures and credentials.

 async authorize(credentials) {
const { body: { csrfToken } } = req;

const appClient = createAppClient({
ethereum: viemConnector(),
});

const verifyResponse = await appClient.verifySignInMessage({
message: credentials?.message as string,
signature: credentials?.signature as `0x${string}`,
domain: "example.com",
nonce: csrfToken,
});
const { success, fid } = verifyResponse;

if (!success) {
return null;
}

return {
id: fid.toString(),
name: credentials?.name,
image: credentials?.pfp,
};
},

Step 3: Generate a JWT Token using Farcaster User's data

a. Create a JWT Token: Create an API endpoint to generate JWT tokens containing user's data from Farcaster. Follow these steps to setup your Custom Verifier with Web3Auth. pages/api/login.ts

import jwt from "jsonwebtoken";

b. JWT Signing: Sign the JWT token using a private key and include necessary user data that you get from Farcaster.

const userData = req.body.userData;
// Get RS256 key of length 2048
const privateKey = process.env.PRIVATE_KEY!;

const jwtToken = jwt.sign(
{
sub: userData?.fid.toString(),
name: userData?.displayName,
username: userData?.username,
profileImage: userData?.pfpUrl,
custody: userData?.custody,
aud: "w3a:farcaster-server",
iss: "https://web3auth.io",
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 60 * 60,
},
privateKey,
{ algorithm: "RS256", keyid: "REPLACE_KEY_ID" },
);

Step 4: Authenticate with Web3Auth

a. Initialize Web3Auth SFA JS SDK: Set up Web3Auth instance and configure it with necessary parameters.

import { Web3Auth, decodeToken } from "@web3auth/single-factor-auth";
import { EthereumPrivateKeyProvider } from "@web3auth/ethereum-provider";
import { ADAPTER_EVENTS, CHAIN_NAMESPACES, IProvider, WEB3AUTH_NETWORK } from "@web3auth/base";

const web3auth = new Web3Auth({
clientId: "WEB3AUTH_CLIENT_ID", // Get your Client ID from the Web3Auth Dashboard
web3AuthNetwork: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,
});

const privateKeyProvider = new EthereumPrivateKeyProvider({
config: {
chainConfig: {
chainNamespace: CHAIN_NAMESPACES.EIP155,
chainId: "0xaa36a7",
rpcTarget: "https://rpc.ankr.com/eth_sepolia",
displayName: "Ethereum Sepolia Testnet",
blockExplorerUrl: "https://sepolia.etherscan.io",
ticker: "ETH",
tickerName: "Ethereum",
},
},
});

// Use it inside useEffect
await web3auth.init(privateKeyProvider);

b. Get idToken from your backend:

const response = await fetch("/api/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ userData: res }),
});
const data = await response.json();
const token = data.token;

c. Initiate Web3Auth Login:

Implement login functionality using the generated JWT token.

const login = async (idToken: any) => {
// Login logic
if (!web3auth.ready) {
console.log("web3auth initialised yet");
return;
}
const { payload } = decodeToken(idToken);

const web3authProvider = await web3auth.connect({
verifier, // verifier name from the Web3Auth dashboard
verifierId: (payload as any).sub, // based on your setup
idToken, // token from the backend
});
return web3authProvider;
};

Step 5 (Optional): Additional Features

a. Blockchain Interactions: Include optional features like checking balances, signing messages, and sending transactions.

const getBalance = async (provider: IProvider) => {
// Get balance logic
};

b. Logout Functionality: Implement logout functionality for users.

const logOut = async () => {
await web3auth.logout();
await signOut();
};

Full Implementation Example

Here's an example of how to integrate the above steps into your Next.js application


This guide should provide a clear structure and step-by-step instructions for integrating Sign In with Farcaster using Web3Auth SFA JS SDK. Let me know if you need further clarification on any part!