{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"\ud83d\udd10 react-auth \u2014 Authentication UI and State","text":"
react-auth is the front-end half of the Aetos auth story: a JWT-backed AuthProvider, a pluggable login/register screen, profile screens, and an axios factory that carries bearer tokens and reacts to 401 responses. The server side lives in the Auth Server service; this package never defines an endpoint contract of its own.
Doc model: this wiki is written for humans \u2014 guides and wiring recipes. The authoritative API contracts live in the code (RDFC JSDoc) and the machine-readable bundle under docs/mcp/. Browse the TypeDoc site for the full symbol reference.
AuthProvider + useAuth \u2014 current user, token, loading and error state with login / register / logoutcreateApiClient \u2014 axios with Authorization: Bearer <token> on every request and auth:unauthorized dispatch on 401AuthPage \u2014 a ready-made split-screen login/register formProfileCreate / ProfileEdit / ProfileView \u2014 presentational profile screens that delegate persistence to your callbackstokenStore \u2014 the single localStorage accessor keeping the UI and the network layer in syncimport { AuthProvider, useAuth, AuthPage } from \"react-auth\";\n\nexport default function Root() {\n return (\n <AuthProvider\n authConfig={{\n serverUrl: \"https://api.example.com\",\n loginPath: \"/auth/login\",\n registerPath: \"/auth/register\",\n logoutPath: \"/auth/logout\",\n mePath: \"/auth/me\",\n introspectPath: \"/auth/introspect\",\n }}\n >\n <LoginGate />\n </AuthProvider>\n );\n}\n"},{"location":"#related-resources","title":"\ud83d\udd17 Related Resources","text":"react-auth repositorylib HTML for the full API referencedocs/mcp/ (docs://modules/react-auth)react-auth (MCP :8011)authConfig \u2014 read docs://spec on the standards MCP for the pinned contract\u00a9 Aetoskia Internal \u2014 react-auth 0.0.1
react-auth owns three concerns and nothing else: session state, the authenticated HTTP client, and the screens that produce a session. It talks to an auth server over HTTP \u2014 it never issues, validates or decodes tokens itself.
contexts.tsx AuthProvider, useAuth, AuthServerConfig Authenticated HTTP client axios.ts createApiClient, attachAuthInterceptors Token persistence token.ts tokenStore (localStorage, key \"token\") Login / register screen AuthPage.tsx AuthPage, AuthMode Profile screens Profile*.tsx controlled presentational components User model models.ts AuthUser The package entry (index.ts) re-exports the public surface; nothing else in the app should import the internals directly.
AuthProvider seeds its token from tokenStore.get().mePath is fetched and currentUser is set (or cleared).login(username, password) posts to loginPath, stores access_token through tokenStore, and takes currentUser from the response user.register(...) creates the account, then logs in.createApiClient attaches Authorization: Bearer <token> from tokenStore.401 clears the token and dispatches an auth:unauthorized window event; AuthProvider listens, clears the session, and invokes the optional onUnauthorized callback.logoutPath, then local state is always cleared.One source of truth
tokenStore is the only place the token is written. Reading it from anywhere else will desynchronise the UI from the network layer.
AuthServerConfig is the complete wiring surface; every path resolves relative to serverUrl:
loginPath POST { username, password } \u2192 { access_token, user } registerPath POST { username, password } to create an account logoutPath called on logout; failures are ignored mePath returns the current AuthUser for a valid bearer token introspectPath token introspection, available to callers that need it AuthUser is intentionally permissive so it can be spread into application state without loss.
Recipes for the three things every Khata front-end does: mount the provider, gate on the session, and edit the profile. All of these are presentational \u2014 swap in your own router or layout as needed.
"},{"location":"02_wiring/#1-mount-the-provider","title":"\ud83d\udce6 1. Mount the provider","text":"import { AuthProvider } from \"react-auth\";\nimport type { AuthServerConfig } from \"react-auth\";\n\nconst authConfig: AuthServerConfig = {\n serverUrl: \"https://api.example.com\",\n loginPath: \"/auth/login\",\n registerPath: \"/auth/register\",\n logoutPath: \"/auth/logout\",\n mePath: \"/auth/me\",\n introspectPath: \"/auth/introspect\",\n};\n\nexport default function Root() {\n return (\n <AuthProvider authConfig={authConfig} onUnauthorized={() => console.info(\"session expired\")}>\n <App />\n </AuthProvider>\n );\n}\n AuthProvider must wrap any component that calls useAuth.
import { useAuth, AuthPage } from \"react-auth\";\nimport { useState } from \"react\";\n\nfunction LoginGate({ children }: { children: React.ReactNode }) {\n const auth = useAuth();\n const [mode, setMode] = useState<\"login\" | \"register\">(\"login\");\n\n if (auth.currentUser) return <>{children}</>;\n\n return (\n <AuthPage\n mode={mode}\n onBack={() => history.back()}\n onSwitchMode={() => setMode((m) => (m === \"login\" ? \"register\" : \"login\"))}\n login={auth.login}\n register={auth.register}\n loading={auth.loading}\n error={auth.error}\n currentUser={auth.currentUser}\n />\n );\n}\n Automatic redirect
AuthPage calls onBack on its own once currentUser becomes truthy, so it works as a route guard without a useEffect. mode is fully controlled, so the login/register toggle never unmounts the form.
ProfileCreate, ProfileEdit and ProfileView render the profile UI and delegate persistence to callbacks you supply \u2014 the library does not know how your backend stores profiles.
The three screens take flat props, not a user object:
Component PropsProfileView name, username, email, onEdit?, loading? ProfileEdit name, username, email, onSubmit, onBack?, loading?, error? ProfileCreate onSubmit, defaultUsername?, defaultEmail?, onBack?, loading?, error? import { ProfileView, ProfileEdit, useAuth } from \"react-auth\";\nimport { useState } from \"react\";\n\nfunction ProfileRoute() {\n const { currentUser } = useAuth();\n const [editing, setEditing] = useState(false);\n\n if (!currentUser) return null;\n const { username, email } = currentUser;\n const props = { username, email, name: username };\n\n if (editing) {\n return <ProfileEdit {...props} onBack={() => setEditing(false)} onSubmit={saveProfile} />;\n }\n return <ProfileView {...props} onEdit={() => setEditing(true)} />;\n}\n onSubmit always receives { name, email } \u2014 persistence is yours.
Client-side validation only
AuthPage validates username >= 3 and password >= 6 before calling your callback. The auth server remains the authority \u2014 never skip its validation.
import { createApiClient } from \"react-auth\";\n\nconst api = createApiClient(\"https://api.example.com\");\nconst { data } = await api.get(\"/expenses\"); // Authorization added automatically\n Use createApiClient for any backend that shares the auth-server login. A plain axios instance is fine for unauthenticated endpoints.
For an existing client, attachAuthInterceptors(client) decorates it in place with the same request/response behaviour.
docs://spec on the standards MCP