Use with Convex
Authenticate Convex queries and mutations with Shoo
Shoo ships a Convex adapter that plugs directly into ConvexProviderWithAuth.
Install
bun add @shoojs/reactConfigure Convex auth
Add Shoo as a custom JWT provider:
export default {
providers: [
{
type: "customJwt",
issuer: "https://shoo.dev",
jwks: "https://shoo.dev/.well-known/jwks.json",
algorithm: "ES256",
},
],
};To enforce audience checks, add applicationID set to origin:https://your-app-origin.
Wire up the provider
Create a Shoo auth module:
import { createShooConvexAuth } from "@shoojs/react";
export const { useAuth, signIn, signOut } = createShooConvexAuth({
callbackPath: "/shoo/callback",
});Then connect it to your Convex provider:
import { ConvexProviderWithAuth, ConvexReactClient } from "convex/react";
import { useAuth } from "./shoo";
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);
function Root() {
return (
<ConvexProviderWithAuth client={convex} useAuth={useAuth}>
<App />
</ConvexProviderWithAuth>
);
}Sign in and out
import { signIn, signOut } from "./shoo";
function AuthButtons() {
return (
<div>
<button onClick={() => signIn()}>Sign in</button>
<button onClick={signOut}>Sign out</button>
</div>
);
}Access identity in Convex functions
Use identity.subject as your stable user ID:
import { query } from "./_generated/server";
export const viewer = query({
args: {},
handler: async (ctx) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) return null;
return {
userId: identity.subject,
email: identity.email ?? null,
name: identity.name ?? null,
};
},
});What the adapter provides
createShooConvexAuth returns:
| Export | Type | Description |
|---|---|---|
useAuth | () => { isLoading, isAuthenticated, fetchAccessToken } | Hook for ConvexProviderWithAuth |
signIn | (opts?) => Promise<void> | Redirect to Shoo sign-in |
signOut | () => void | Clear identity and reload page |
The useAuth hook handles the callback exchange on mount, reports isAuthenticated based on the stored identity, and returns the id_token via fetchAccessToken for Convex to use.