React integration
React handles the sign-in interface. Your backend owns the OAuth transaction, member signing key, code exchange, and local session. Follow JavaScript or Next.js first.
Start sign-in
Once your backend implements a start route, use a normal browser navigation. The route name here is an application route you create, not a Sigma endpoint.
export function SignInButton() {
return <a href="/auth/sigma/start">Sign in with Sigma</a>;
}The server redirects to Sigma; after consent, the server callback establishes the application session and redirects back. This avoids exposing the client signing key or keeping OAuth tokens in component state/localStorage.
Read a Better Auth session
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient();import { authClient } from "@/lib/auth-client";
export function AccountMenu() {
const { data: session, isPending } = authClient.useSession();
if (isPending) return <p>Loading account…</p>;
if (!session?.user) return <a href="/auth/sigma/start">Sign in</a>;
return (
<button type="button" onClick={() => authClient.signOut()}>
Sign out {session.user.name}
</button>
);
}The client talks to your own application's Better Auth handler by default. A UI session check does not authorize server APIs; verify the session and resource ownership on the server for each request.
Existing browser-plugin integrations
sigmaClient() can start redirects and parse callbacks, as described in the client plugin reference. Its callback uses sessionStorage state and calls your local POST callback endpoint. That endpoint still needs server-side transaction protection.
Handle a callback only once: React effects can run more than once in development, and OAuth codes are single-use. Use one callback owner with a stable in-flight promise, show pending/error states, and offer a new sign-in attempt after failure. Do not retry an already-consumed code or regenerate state midway through a flow.