Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
siwf
✓ import { siwf } from 'better-auth-siwf'
✗ const { siwf } = require('better-auth-siwf')
The server-side plugin function used to configure Better Auth with Farcaster authentication. This package is ESM-first and primarily consumed in TypeScript environments.
siwfClient
✓ import { siwfClient } from 'better-auth-siwf'
✗ const { siwfClient } = require('better-auth-siwf')
The client-side plugin function used with `createAuthClient` from `better-auth/react` to expose SIWF-specific methods on the client.
ResolveFarcasterUserResult
✓ import { type ResolveFarcasterUserResult } from 'better-auth-siwf'
✗ import { ResolveFarcasterUserResult } from 'better-auth-siwf'
TypeScript type import for the return value of the optional `resolveFarcasterUser` callback. Use the `type` keyword for type-only imports to ensure proper tree-shaking and compilation.
SIWFClientType
✓ import { type SIWFClientType } from 'better-auth-siwf'
✗ import { SIWFClientType } from 'better-auth-siwf'
TypeScript type used for augmenting the `createAuthClient` return type, providing type inference for SIWF-specific methods on the client-side `authClient` instance.
Demonstrates setting up the `better-auth-siwf` plugin on both the server and client, including Farcaster JWT acquisition and verification to establish a Better Auth session. It also shows optional Farcaster user data resolution via Neynar.
import { betterAuth } from "better-auth";
import { type ResolveFarcasterUserResult, siwf } from "better-auth-siwf";
import { createAuthClient } from "better-auth/react";
import { siwfClient, type SIWFClientType } from "better-auth-siwf";
// --- Server-side configuration (e.g., auth.ts) ---
const NEYNAR_API_KEY = process.env.NEYNAR_API_KEY ?? ''; // Replace with actual env var or error handling
const auth = betterAuth({
// ... your better-auth config
plugins: [
siwf({
hostname: "app.example.com", // Crucial: must match the domain used in Farcaster Quick Auth
allowUserToLink: false,
resolveFarcasterUser: async ({
fid,
}): Promise<ResolveFarcasterUserResult | null> => {
if (!NEYNAR_API_KEY) {
console.warn("Neynar API key not set. Farcaster user details will not be resolved.");
return null;
}
try {
const response = await fetch(
`https://api.neynar.com/v2/farcaster/user/bulk/?fids=${fid}`,
{
method: "GET",
headers: {
"x-api-key": NEYNAR_API_KEY,
"Content-Type": "application/json",
},
}
);
const data = await response.json();
if (!data || data.users.length === 0) {
return null;
}
const user = data.users[0];
return {
fid,
username: user.username,
displayName: user.display_name,
avatarUrl: user.pfp_url,
custodyAddress: user.custody_address,
verifiedAddresses: {
primary: {
ethAddress: user.verified_addresses.primary?.eth_address ?? undefined,
solAddress: user.verified_addresses.primary?.sol_address ?? undefined,
},
ethAddresses: user.verified_addresses?.eth_addresses ?? undefined,
solAddresses: user.verified_addresses?.sol_addresses ?? undefined,
},
} satisfies ResolveFarcasterUserResult;
} catch (error) {
console.error("Error resolving Farcaster user with Neynar:", error);
return null;
}
},
}),
],
});
// --- Client-side configuration (e.g., auth-client.ts) ---
// Assume miniappSdk is available in a Farcaster MiniApp environment
declare const miniappSdk: { quickAuth: { getToken: () => Promise<{ token: string }> }, context: Promise<{ user: any; client: { clientFid: string; notificationDetails?: any } }> };
const client = createAuthClient({
plugins: [siwfClient()],
fetchOptions: {
credentials: "include", // Required for session cookies
},
});
export const authClient = client as typeof client & SIWFClientType;
// --- Client-side usage (e.g., in a React component) ---
async function signIn() {
try {
// 1) Obtain a Farcaster JWT token on the client
const result = await miniappSdk.quickAuth.getToken(); // result: { token: string }
// 2) Verify and sign in with the Better Auth server
const ctx = await miniappSdk.context;
const { data } = await authClient.signInWithFarcaster({
token: result.token,
user: {
...ctx.user,
notificationDetails: ctx.client.notificationDetails
? [
{
...ctx.client.notificationDetails,
appFid: (await miniappSdk.context).client.clientFid
}
]
: [],
}
});
if (data.success) {
console.log("Signed in successfully! User:", data.user);
// Redirect or update UI
} else {
console.error("Farcaster sign-in failed:", data.error);
}
} catch (error) {
console.error("An error occurred during Farcaster sign-in:", error);
}
}
signIn(); // Call this function from your client-side logic
Errors
Common errors & fixes
TypeError: authClient.signInWithFarcaster is not a function
The `siwfClient()` plugin was not added to `createAuthClient`, or the client instance was not correctly type-augmented with `SIWFClientType`.
fixEnsure `createAuthClient({ plugins: [siwfClient()] })` is configured and that `export const authClient = client as typeof client & SIWFClientType;` is used. Farcaster JWT verification failed: Invalid domain
The `hostname` configured in the server-side `siwf` plugin does not match the `domain` provided during Farcaster Quick Auth on the client.
fixVerify that `siwf({ hostname: 'your.domain.com' })` on the server and the domain parameter used when obtaining the Farcaster JWT on the client (e.g., `miniappSdk.quickAuth.getToken({ domain: 'your.domain.com' })`) are identical. Error: Missing NEYNAR_API_KEY environment variable (or similar API key error from `resolveFarcasterUser`)
The `resolveFarcasterUser` callback, if implemented to use an external API like Neynar, requires an API key that was not provided or was incorrect.
fixSet the `NEYNAR_API_KEY` (or equivalent) environment variable on your server where `better-auth` is running, or ensure the key is correctly passed to your API calls within `resolveFarcasterUser`.
Audit
Dependencies
better-authrequiredPeer dependency required for the core authentication framework this plugin extends.