@fractalshq/auth-react
v0.1.17
Published
Adapter-agnostic React helpers for cookie-based SIWS auth. No tokens in localStorage; session lives in HTTP-only cookies.
Readme
@fractalshq/auth-react
Adapter-agnostic React helpers for cookie-based SIWS auth. No tokens in localStorage; session lives in HTTP-only cookies.
Quick start
import { AuthProvider, useAuth } from "@fractalshq/auth-react";
export default function App() {
return (
<AuthProvider baseURL="/api">
<Login />
</AuthProvider>
);
}
function Login() {
const { user, status, loginWithWallet, logout } = useAuth();
const connect = async () => {
const publicKey = await getPubkey();
const sign = (m: string) => wallet.signMessage(m);
await loginWithWallet({ publicKey, sign, provider: "phantom" });
};
return (
<div>
{status !== "authenticated" ? (
<button onClick={connect}>Sign in</button>
) : (
<>
<pre>{JSON.stringify(user, null, 2)}</pre>
<button onClick={logout}>Sign out</button>
</>
)}
</div>
);
}Wallet provider & defaults
@fractalshq/auth-react now ships an opinionated wallet wrapper that wires @solana/wallet-adapter-react, default adapters (Phantom, Solflare, Trust, Coinbase, Safe Ledger), and Ledger derivation state.
import {
FractalsWalletProvider,
useFractalsWallet,
useLedgerDerivation,
LedgerDerivationToggle,
} from "@fractalshq/auth-react";
export default function App() {
return (
<FractalsWalletProvider network="mainnet-beta">
<AuthProvider baseURL="/api">{/* ... */}</AuthProvider>
</FractalsWalletProvider>
);
}
function WalletSummary() {
const { publicKey, isLedgerWallet } = useFractalsWallet();
const { mode } = useLedgerDerivation();
return (
<div>
<p>Connected wallet: {publicKey?.toBase58() ?? "—"}</p>
{isLedgerWallet && <LedgerDerivationToggle showDescription />}
</div>
);
}Reminder: import
@solana/wallet-adapter-react-ui/styles.cssonce in your app if you use the provided modal.
Hooks
import { useActiveOrg, useHasOrgRole, useHasPlatformRole, FRACTALS_PLATFORM_ID } from "@fractalshq/auth-react";
const { id: activeOrgId, role } = useActiveOrg();
const canManageOrg = useHasOrgRole(activeOrgId!, ["admin", "distributor"]);
const isPlatformAdmin = useHasPlatformRole(FRACTALS_PLATFORM_ID, ["admin"]);Headless client (no Provider)
import { createClient } from "@fractalshq/auth-react";
const client = createClient({ baseURL: "/api" });
const { message } = await client.createNonce(pubkey);
const sig = await sign(message);
await client.signInSiws({ publicKey: pubkey, signature: sig, message });
const me = await client.getMe();Ledger support
Ledger devices are supported via transaction-based authentication that works with hardware wallets. We never access private keys; users must verify transactions on-device.
Prerequisites
- Ledger device with latest firmware
- Solana app installed and open on the device
@solana/web3.jsinstalled (see Web3 Adapter Setup below)
Install dependencies
# Required for web3 operations
npm install @solana/web3.js
# Choose one Ledger integration:
# Option A — Ledger Wallet API Client (via Ledger Live / Connect Kit):
npm install @ledgerhq/wallet-api-client @ledgerhq/connect-kit-loader
# Option B — Direct device transport (advanced):
npm install @ledgerhq/hw-transport-webhid @ledgerhq/hw-app-solanaWeb3 Adapter Setup (Required)
Ledger authentication requires a web3 adapter. Add this to your app's providers:
import { Transaction, PublicKey, TransactionInstruction, SystemProgram } from '@solana/web3.js';
import { AuthProvider, Web3Adapter } from '@fractalshq/auth-react';
const web3Adapter: Web3Adapter = {
Transaction,
PublicKey,
TransactionInstruction,
SystemProgram,
};
export default function App() {
return (
<AuthProvider baseURL="/api" web3Adapter={web3Adapter}>
{/* Your app */}
</AuthProvider>
);
}See Ledger docs for setup and security notes: https://developers.ledger.com.
Usage with React Provider
import { AuthProvider, useAuth } from "@fractalshq/auth-react";
import { Connection } from "@solana/web3.js";
export default function App() {
return (
<AuthProvider baseURL="/api" web3Adapter={web3Adapter}>
<LedgerLogin />
</AuthProvider>
);
}
function LedgerLogin() {
const { loginWithLedger } = useAuth();
const connectLedger = async () => {
// Implement using your chosen Ledger integration:
const signer = await getLedgerSolanaSigner(); // Returns a WalletSigner
const connection = new Connection("https://api.mainnet-beta.solana.com");
await loginWithLedger({
signer,
connection,
provider: "ledger"
});
};
return <button onClick={connectLedger}>Sign in with Ledger</button>;
}The getLedgerSolanaSigner() should encapsulate your chosen Ledger integration. For example:
- With Wallet API Client: establish a session via Connect Kit, select a Solana account, expose
{ publicKey, sign }. - With WebHID: use
@ledgerhq/hw-transport-webhid+@ledgerhq/hw-app-solanato derive{ publicKey, sign }.
Headless usage
import { createClient } from "@fractalshq/auth-react";
import { Connection } from "@solana/web3.js";
const client = createClient({
baseURL: "/api",
web3Adapter: { Transaction, PublicKey, TransactionInstruction, SystemProgram }
});
const signer = await getLedgerSolanaSigner(); // Returns a WalletSigner
const connection = new Connection("https://api.mainnet-beta.solana.com");
await client.loginWithLedgerSigner({
signer,
connection,
provider: "ledger"
});Security considerations
- Always verify the address and message on the Ledger device screen.
- Do not trust unsigned UI prompts; confirmation must occur on device.
- Never persist private keys; only use device-backed signatures.
