@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>
);
}
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 an external signer that provides a Solana public key and a message-signing function. We never access private keys; users must verify on-device.
Prerequisites
- Ledger device with latest firmware
- Solana app installed and open on the device
Install one of the official Ledger integrations
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-solana
See Ledger docs for setup and security notes: https://developers.ledger.com.
Usage with React Provider
import { AuthProvider, useAuth } from "@fractalshq/auth-react";
export default function App() {
return (
<AuthProvider baseURL="/api">
<LedgerLogin />
</AuthProvider>
);
}
function LedgerLogin() {
const { loginWithWallet } = useAuth();
const connectLedger = async () => {
const { publicKey, sign } = await getLedgerSolanaSigner();
await loginWithWallet({ publicKey, sign, 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-solana to derive { publicKey, sign }.
Headless usage
import { createClient } from "@fractalshq/auth-react";
const client = createClient({ baseURL: "/api" });
const { publicKey, sign } = await getLedgerSolanaSigner();
const { message } = await client.createNonce(publicKey);
const signature = await sign(message);
await client.signInSiws({ publicKey, signature, message });
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.