Better Auth Plugin for Solana Sign-In
better-auth-solana is a specialized plugin for the Better Auth authentication framework, designed to facilitate "Sign in With Solana" (SIWS) functionality. Currently at version 1.0.0, it provides a stable, initial release enabling Solana wallet integration into Better Auth applications. The package includes server-side endpoints for managing the SIWS flow (nonce generation, signature verification, wallet linking) and client-side utilities for constructing SIWS messages and interacting with the Better Auth client. It natively handles session establishment and account creation/linking within the Better Auth ecosystem, using its dedicated `siws` plugin namespace. The package is published as ESM-only, aligning with better-auth's modern module strategy.
Common errors
-
ERR_REQUIRE_ESM
cause Attempting to use `require()` to import `better-auth-solana` or its subpaths in a CommonJS module.fixMigrate your file or project to use ES Modules (`import ... from '...'`) or dynamically import the package using `await import(...)`. -
Failed to request SIWS nonce
cause The server-side `/siws/nonce` endpoint did not return a challenge, possibly due to a network issue, server misconfiguration, or an invalid `walletAddress` provided.fixVerify the server is running and the `siws` plugin is correctly configured. Check network requests in your browser's developer tools for errors from the `/siws/nonce` endpoint and ensure `walletAddress` is valid. -
Error: Invalid SIWS message format
cause The `message` or `signature` provided to `authClient.siws.verify` (or `link`) does not match the expected SIWS format or fails signature verification.fixEnsure `createSIWSInput` or `createSIWSMessage` is used correctly to generate the message. Confirm the wallet's `signMessage` function is returning the expected message and a valid signature. The `domain`, `uri`, and other SIWS fields must match those expected by the server.
Warnings
- breaking The `better-auth-solana` package is ESM-only (ECMAScript Modules) since its initial v1.0.0 release. Attempts to `require()` it in a CommonJS environment will result in module resolution errors.
- gotcha This package has peer dependencies on `@solana/kit` (`^6.8.0`) and `better-auth` (`^1.5.0`). These must be installed separately in your project and meet the specified version constraints for `better-auth-solana` to function correctly.
- gotcha When using client-side verification, differentiate between `authClient.siws.verify(...)` for establishing a new Better Auth session or logging in, and `authClient.siws.link(...)` for attaching a new Solana wallet to an *already authenticated* Better Auth session.
- gotcha The plugin uses a fixed `siws` namespace, which means its API endpoints will always be nested under your Better Auth handler's path, e.g., `/api/auth/siws/verify`.
Install
-
npm install better-auth-solana -
yarn add better-auth-solana -
pnpm add better-auth-solana
Imports
- siws
const { siws } = require('better-auth-solana')import { siws } from 'better-auth-solana' - createSIWSInput
const { createSIWSInput } = require('better-auth-solana/client')import { createSIWSInput } from 'better-auth-solana/client' - siwsClient
const { siwsClient } = require('better-auth-solana/client')import { siwsClient } from 'better-auth-solana/client' - formatSIWSMessage
const { formatSIWSMessage } = require('better-auth-solana/client')import { formatSIWSMessage } from 'better-auth-solana/client'
Quickstart
import { createAuthClient } from 'better-auth/client'
import { createSIWSInput, siwsClient } from 'better-auth-solana/client'
// Placeholder for your wallet's sign function
async function signWithYourWallet(siwsInput: any): Promise<{ message: string; signature: string }> {
console.log('Signing message with wallet:', siwsInput)
// In a real app, this would involve connecting to a Solana wallet (e.g., Phantom, Solflare)
// and using its sign message functionality. For demonstration, we'll return a mock.
const mockSignature = 'mock_signature_' + Date.now()
return { message: JSON.stringify(siwsInput), signature: mockSignature }
}
// Assume 'address' is the connected Solana wallet address
const address = 'GMtGgT8d6R3FwYxK2c3L4p5Q6r7S8t9U0v1W2x3Y4z5'
const authClient = createAuthClient({
plugins: [siwsClient()],
})
async function performSolanaSignIn() {
try {
const nonceResult = await authClient.siws.nonce({
walletAddress: address,
})
if (!nonceResult.data) {
throw new Error('Failed to request SIWS nonce')
}
const siwsInput = createSIWSInput({
address,
challenge: nonceResult.data,
statement: 'Sign in to Example',
domain: 'example.com', // Must match the domain configured on the server
uri: 'https://example.com/siws', // The current application URI
chainId: 'solana:mainnet', // Solana network chain ID
version: '1' // SIWS version
})
const signed = await signWithYourWallet(siwsInput)
await authClient.siws.verify({
message: signed.message,
signature: signed.signature,
walletAddress: address,
})
const session = await authClient.getSession()
console.log('Successfully signed in:', session)
} catch (error) {
console.error('SIWS sign-in failed:', error)
}
}
performSolanaSignIn()