Registry / auth-security / better-auth-siwf

better-auth-siwf

JSON →
library1.0.28jsnpmunverified

The `better-auth-siwf` package provides a plugin for the `better-auth` framework, enabling users to authenticate via Farcaster identities. It mirrors the developer experience of the official Sign In With Ethereum (SIWE) plugin, adapting the authentication flows and schema for Farcaster. This plugin handles the server-side verification of Farcaster Quick Auth JWTs, establishes Better Auth session cookies, and can optionally resolve enriched Farcaster user data via a provided callback (e.g., from Neynar API). The current stable version is 1.0.28. While a specific release cadence isn't stated, the 1.0.x versioning suggests a focus on stability with incremental improvements. Its key differentiator is its seamless integration with the `better-auth` ecosystem, offering a standardized approach to Farcaster authentication within that framework.

npm install better-auth-siwf
INSTALL
IMPORT
SIG · BETTER-AUTH-SIWF
B
better-auth-siwf
auth-securityjavascriptv1.0.28
Install
Import
Disk
Pass rate
0/ 6
Env Coverage0 / 6
glibc
1822
musl
1822
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
musl
node 18226 runs
build_error
glibc
node 18226 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
Debug
Known issues
gotchaThe `hostname` configured in the server-side `siwf` plugin MUST exactly match the `domain` used when obtaining the JWT via Farcaster Quick Auth on the client. A mismatch will cause JWT verification to fail.
fix
Ensure `siwf({ hostname: 'your.domain.com' })` on the server and `miniappSdk.quickAuth.getToken({ domain: 'your.domain.com' })` on the client use identical domain names.
affects: >=1.0.0
gotchaThe client-side `createAuthClient` configuration requires `fetchOptions: { credentials: 'include' }` to ensure that the session cookie set by the `better-auth-siwf` plugin on the server is correctly sent and received by the browser.
fix
Add `fetchOptions: { credentials: 'include' }` to your `createAuthClient` call, as shown in the quickstart example.
affects: >=1.0.0
gotchaWhen augmenting the `authClient` type with `SIWFClientType`, ensure you use `import { type SIWFClientType } from 'better-auth-siwf'` with the `type` keyword. Omitting `type` can lead to bundling issues or unexpected behavior in some environments.
fix
Always use `import { type SIWFClientType } from 'better-auth-siwf'` for type-only imports.
affects: >=1.0.0
gotchaThe `resolveFarcasterUser` callback is optional but highly recommended for enriching the user profile with details like username, display name, and avatar URL from a Farcaster-compatible API (e.g., Neynar). Without it, only basic FID and address information will be available.
fix
Implement the `resolveFarcasterUser` callback and integrate with a Farcaster API (like Neynar) to fetch and return detailed user information.
affects: >=1.0.0
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`.
fix
Ensure `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.
fix
Verify 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.
fix
Set 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`.
Upgrade
Version history
1.0.28latest on npm
Audit
Dependencies
better-authrequiredPeer dependency required for the core authentication framework this plugin extends.
Agent activity
24 hits · last 30 days
node
18
OpenAI (training)
1
Resources
better-auth-siwf — npm install better-auth-siwf · libregistry