Better Auth Worldcoin Minikit Plugin

1.0.10 · active · verified Wed Apr 22

The `better-auth-minikit` package provides a plugin for the `better-auth` authentication library, enabling seamless integration with Worldcoin Minikit for Sign-In With Ethereum (SIWE) based authentication flows. It is currently at version 1.0.10, indicating a stable release within its first major iteration. While a specific release cadence isn't stated, the `better-auth` ecosystem generally follows a responsive approach to updates. Key differentiators include its full SIWE implementation adapted for Minikit, robust multi-chain support for associating wallet addresses with specific chain IDs, automatic account linking for verified multiple wallet addresses, and compatibility with MiniApps via secure, partitioned session cookies (SameSite: "none"). It abstracts much of the SIWE complexity for `better-auth` users, focusing on secure server-side nonce generation and message verification, along with a client-side API for initiating the flow.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates both the server-side configuration of the `minikit` plugin for `better-auth` and the client-side setup and usage with `minikitClient`, covering nonce retrieval, SIWE message signing with Worldcoin Minikit, and final sign-in verification.

import { betterAuth } from "better-auth";
import { minikit } from "better-auth-minikit";
import { generateRandomString } from "better-auth/crypto";
import { parseSiweMessage, validateSiweMessage } from "viem/siwe";
import { createAuthClient } from "better-auth/react";
import { minikitClient } from "better-auth-minikit/client";
import { MiniKit } from '@worldcoin/minikit-js';
import { createSiweMessage } from 'viem/siwe'; // Helper to create SIWE messages

// --- Server Setup (Node.js/Edge Function) ---
export const auth = betterAuth({
  plugins: [
    minikit({
      domain: "app.example.com", // Replace with your actual domain
      getNonce: async () => {
        return generateRandomString(32);
      },
      verifyMessage: async ({ message, signature, address, chainId }) => {
        try {
            const parsedMessage = await parseSiweMessage(message);
            const valid = await validateSiweMessage({
                message,
                signature,
                domain: "app.example.com",
                nonce: parsedMessage.nonce,
                address: address, // Ensure address is passed for robust validation
                chainId: chainId // Ensure chainId is passed for robust validation
            });
            return valid;
        } catch (e) {
            console.error("SIWE message verification failed:", e);
            return false;
        }
      }
    })
  ]
});

// --- Client Setup (React Component or similar) ---
const client = createAuthClient({
  plugins: [minikitClient()],
  fetchOptions: {
    credentials: "include", // Essential for session cookies in MiniApps
  },
});

export const authClient = client;

// --- Client-side Usage Example (within an async function) ---
async function authenticateWithWorldcoin() {
  const walletAddress = "0x..."; // User's actual wallet address from Minikit
  const chainId = 1; // Example: Ethereum Mainnet

  // 1. Get Nonce
  const { data: nonceData, error: nonceError } = await authClient.minikit.getNonce({
    walletAddress,
    chainId
  });
  if (nonceError || !nonceData?.nonce) {
    console.error("Failed to get nonce:", nonceError);
    return;
  }
  const nonce = nonceData.nonce;

  // 2. Sign Message (using Worldcoin Minikit SDK)
  const message = createSiweMessage({
      domain: window.location.host,
      address: walletAddress,
      statement: "Sign in to My App",
      uri: window.location.origin,
      version: "1",
      chainId: chainId,
      nonce: nonce,
  });

  let signature;
  try {
    // This part requires Worldcoin Minikit to be initialized and available
    const { commandPayload } = await MiniKit.commands.signMessage({
        message: message
    });
    signature = commandPayload;
  } catch (signError) {
    console.error("Failed to sign message with Minikit:", signError);
    return;
  }

  // 3. Verify and Sign In
  const { data: signInData, error: signInError } = await authClient.minikit.signInWithMinikit({
    message,
    signature,
    walletAddress,
    chainId,
    user: {
        username: "worldcoin-user",
        profilePictureUrl: "https://example.com/default.png"
    }
  });

  if (signInData?.success) {
    console.log("Successfully signed in user:", signInData.user);
  } else {
    console.error("Sign-in failed:", signInError);
  }
}

// Call the function to initiate authentication (example)
// authenticateWithWorldcoin();

view raw JSON →