Skip to content

Latest commit

 

History

History
45 lines (27 loc) · 3.43 KB

File metadata and controls

45 lines (27 loc) · 3.43 KB

This is a vanilla React + Vite SPA, not Next.js

If your training data points you toward server components, server actions, edge middleware, or any next-auth API — those don't apply here. There is exactly one runtime: the browser.

Building new routes and components

Everything auth- and GraphQL-related lives in src/lib/matthews-auth-graphql/. The package exposes one import path:

  • @/lib/matthews-auth-graphqlMatthewsAuthGraphqlProvider, RequireAuth, LoginCallback, useAuth (re-exported from react-oidc-context).

When adding a page or component under src/pages/** or src/components/**, trust the wrapper:

  • Do not create new ApolloClient instances.
  • Do not wrap any tree in another <AuthProvider> — the umbrella in src/App.tsx already does it.
  • Do not implement token-refresh, 401 retry, or session polling — they're already handled inside the package.
  • Use useQuery / useMutation / useSuspenseQuery from @apollo/client/react. The provider above you has wired them up.
  • Use useAuth from @/lib/matthews-auth-graphql for session metadata (the user's profile.name, profile.email, error); never to pull the access token for a hand-rolled fetch.

Protecting routes

Wrap a route element in <RequireAuth>:

<Route element={<RequireAuth />}>
  <Route path="/" element={<Index />} />
</Route>

RequireAuth calls signinRedirect() for unauthenticated users (sending them straight to Okta's hosted sign-in page) and renders nothing while the OIDC session is hydrating. There is no /login page we own — the user goes from the protected route straight to Okta and back.

If something you need isn't covered by the package, surface the gap (ask the user, or extend the package deliberately). Don't bypass the wrapper with ad-hoc code.

Don't do this — silent anti-patterns

The four patterns below are what an agent reaches for by reflex when they skip the helpers above. Three of the four fail silently — tests pass, TypeScript is quiet, runtime looks fine — until a refresh edge case manifests in production. Treat each as a bug.

  1. new ApolloClient(...) in a component. Bypasses the authLink → refreshLink → httpLink chain entirely. Token refresh silently no-ops; the component sees 401s it can't explain. Use useQuery / useMutation / useSuspenseQuery from @apollo/client/react.

  2. A second <AuthProvider> wrapping a subtree. react-oidc-context won't crash, but the inner provider opens a separate session lifecycle and the two will fight over storage keys. The umbrella in App.tsx already installs one.

  3. Hand-rolled refresh on top of useAuth(). Conflicts with refreshLink's single-retry guarantee and with oidc-client-ts's built-in serialization of silent renews. If you think you need this, the answer is no — file a bug against the package instead.

  4. Raw fetch(GRAPHQL_URL, { headers: { Authorization: Bearer ${user.access_token} }}). Works once, then breaks when the access token expires — no refreshLink, no retry. Agents reach for this when writing a non-Apollo HTTP call to the GraphQL API; don't. For a truly non-GraphQL authenticated HTTP call to some other service, stop and ask — no fetchWithAuth helper exists yet and the correct abstraction depends on which service.

If you're about to write any of the four, the root cause is almost always "I didn't know matthews-auth-graphql handles that." Re-read the sections above.