Skip to content

useAuth

useAuth() is the primary hook for reading authentication state. It returns the signed-in flags, the current user and userProfile, the user’s organizations, and the imperative helpers you need to attach a token to a backend call or sign the user out. For switching the active org or managing memberships, use useOrganizations().

This is Torii’s curated public auth surface, deliberately kept to the small, familiar shape auth SDKs expose. The provider’s context carries more fields that the SDK’s own components read internally; those are not part of this hook.

  • Gate UI on isSignedIn (or use <SignedIn> / <SignedOut>).
  • Read the current user / userProfile for display.
  • Get a bearer token for your own backend calls (getToken(), async, refreshes near expiry).
  • Sign the user out, or re-fetch the session after a gate completes.
import { useAuth } from '@torii-js/torii-react';
function Account() {
const { isLoaded, isSignedIn, userProfile, getToken, signOut } = useAuth();
if (!isLoaded) return null;
if (!isSignedIn) return <a href="/sign-in">Sign in</a>;
async function callApi() {
const token = await getToken();
await fetch('/api/me', { headers: { Authorization: `Bearer ${token}` } });
}
return (
<>
<span>{userProfile?.name ?? userProfile?.email}</span>
<button onClick={callApi}>Load</button>
<button onClick={() => signOut()}>Sign out</button>
</>
);
}

useAuth() throws if called outside a <ToriiProvider>.

Name Type Description
isLoaded boolean true once the initial session probe has settled. Render gates should wait for this before trusting isSignedIn.
isLoading boolean true while the initial session probe is in flight.
isSignedIn boolean true when the user has an active session with no pending gates.
user User | null Identity decoded from the JWT (id, emailVerified), or null when signed out. For full fields use userProfile.
userProfile UserProfileData | null Full profile from /me: email, name, locale, etc. null until the boot probe resolves.
organizations ClientOrganizationSummary[] Organizations the user belongs to in this environment ({ id, name, role, role_name? }); empty when signed out or with no memberships. Use useOrganizations() to switch the active org or manage members.
require (params: { role } | { permission }) => boolean Role/permission authorization check. true when the active-organization session satisfies the check, e.g. require({ role: 'org:administrator' }) or require({ permission: 'org:reports:view' }). false with no active org. System permissions (org:sys_*) aren’t in the token, so check the role instead. Declarative form: <Show when={…}>; full guide: Organizations & roles.
getToken (options?: { template?: string }) => Promise<string | null> Async. Returns a usable access token, refreshing first if the current one is missing or within ~30s of expiry. Pass { template } to mint a one-off token from a named JWT template for a third-party service (Hasura, Supabase, …); that token is returned to you, not stored as the session token. Resolves null if the session ended (or the named template doesn’t exist). Prefer this when attaching a bearer token to your own requests.
getAccessToken () => string | null Sync. Reads the current access token as-is, with no refresh. Returns null when signed out. Use when you need the token synchronously and can tolerate a near-expiry value.
sessionExpiresAt Date | null When the current session expires. null when signed out or not yet known.
getDevSessionToken () => string | null Sync. The development session token, or null when there isn’t one. Only sandbox environments have one; always null in production. See the note below.
signIn (tokens: AuthTokens) => void Apply tokens from a successful sign-in / sign-up response. Flips session state in-page.
signOut () => Promise<void> Revoke the session server-side and clear local tokens.
refreshSession () => Promise<void> Re-fetch /me and update userProfile + session gates. Call after any action that may clear a session gate.
currentLanguage string The active language code.
setLanguage (code: string) => void Switch to a different configured language.
runtimeIncompatible boolean true once the server reports this SDK build is too old for an endpoint and the page must reload. Read it to render your own refresh prompt (<ToriiProvider> shows one automatically).
  • getToken() vs getAccessToken(): getToken() is the one to reach for when calling your backend: it refreshes a near-expiry token before handing it back. getAccessToken() is synchronous and never refreshes. For most authed requests, prefer the useAuthFetch() hook, which attaches the bearer and retries on 401 for you.

  • getDevSessionToken(): only relevant when you host sign-in on a different origin from your app during local development — for example an app on localhost:3000 signing in on a page served elsewhere. The session cookie is cross-site there, and browsers that block third-party cookies (Safari and Firefox unconditionally) leave your app signed out after a successful sign-in. To hand the session over, redirect back with the token in the URL fragment alongside the access token, and <ToriiProvider> will pick it up and clear it on load:

    import { HANDOFF_PARAM, useAuth } from '@torii-js/torii-react';
    const { getAccessToken, getDevSessionToken, sessionExpiresAt } = useAuth();
    const accessToken = getAccessToken();
    const devToken = getDevSessionToken();
    // No dev token means production (or no session): the cookie already reaches
    // your app, so leave the URL alone.
    if (accessToken && devToken) {
    const params = new URLSearchParams({ [HANDOFF_PARAM.accessToken]: accessToken });
    if (sessionExpiresAt) {
    params.set(HANDOFF_PARAM.sessionExpiresAt, sessionExpiresAt.toISOString());
    }
    params.set(HANDOFF_PARAM.devSessionToken, devToken);
    window.location.href = `https://myapp.example.com/#${params}`;
    }

    HANDOFF_PARAM holds the fragment parameter names the provider reads. Use it rather than writing the keys out — a mismatch is not a type error, the fragment is simply ignored.

    Both values are required. Gating on the dev token is what keeps this inert in production — never branch on the environment yourself. access_token must be present too: a fragment without it is ignored entirely, so the dev token alone would be silently discarded.

  • Template tokens: getToken({ template: 'hasura' }) mints a one-off token from a named JWT template for a third-party service. It is returned to you (not stored as the session token); resolves null if no such template exists. See JWT templates.

  • Sign-out routing: drive post-sign-out navigation off isSignedIn flipping to false, or events.onSessionExpired on <ToriiProvider>.

import type {
AuthContextValue,
User,
UserProfileData,
ClientOrganizationSummary,
AuthTokens,
} from '@torii-js/torii-react';