087fbdd176
Budget.Core: entities, DTOs, enums, FrequencyCalculator (no EF/ASP.NET deps) Budget.Infrastructure: AppDbContext, migrations, BudgetAuthorizationService Budget.Api: controllers, middleware, Program.cs — references both projects EF and Npgsql packages moved to Infrastructure; Api retains only JwtBearer, HealthChecks, and EF.Design (needed for dotnet ef CLI). Dockerfile updated to copy all three project directories before publishing. Migration namespaces updated from Budget.Api.Data.* to Budget.Infrastructure.Data.* and model type strings updated to Budget.Core.Models.* in the snapshot. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.0 KiB
4.0 KiB
Plan: Replace Custom AuthContext with react-oidc-context
Goal
Replace the hand-rolled AuthContext.tsx / UserManager setup with react-oidc-context,
which wraps oidc-client-ts and handles token expiry events, silent renew errors, and
session monitoring out of the box.
Current state
src/Budget.Client/src/auth/authConfig.ts—UserManagerSettingsobjectsrc/Budget.Client/src/auth/AuthContext.tsx— custom Provider +useAuth()hook, module-levelUserManagersrc/Budget.Client/src/auth/AuthGuard.tsx— reads fromuseAuth()src/Budget.Client/src/pages/CallbackPage.tsx— callsuserManager.signinRedirectCallback()src/Budget.Client/src/api/client.ts—setTokenProvider(fn)wired inmain.tsxsrc/Budget.Client/src/main.tsx— wraps app in<AuthProvider>
Target state
- Remove
AuthContext.tsx. main.tsxwraps the app in<AuthProvider>fromreact-oidc-contextusing the existingauthConfig.AuthGuard.tsxusesuseAuth()fromreact-oidc-context.CallbackPage.tsxbecomes a thin component —react-oidc-contexthandles the callback automatically whenonSigninCallbackis provided toAuthProvider.- A
TokenSynccomponent reads the token fromreact-oidc-contextand pushes it intoapi/client.tsviasetTokenProvider. onSigninCallbacknavigates to/on success but skips navigation when the URL containserror.CallbackPagereadserror/error_descriptionfrom URL params and renders a user-friendly error message.
Steps
Phase 1 — Install
npm install react-oidc-contextinsrc/Budget.Client/.
Phase 2 — Replace AuthProvider
- Delete
src/Budget.Client/src/auth/AuthContext.tsx. - Update
src/Budget.Client/src/main.tsx:- Import
AuthProviderfromreact-oidc-context. - Add
onSigninCallbackthat callswindow.history.replaceState({}, '', '/')unless the URL has?error=. - Wrap the app:
<AuthProvider {...authConfig} onSigninCallback={...}>. - Remove the old
<AuthProvider>import andsetTokenProviderwiring.
- Import
- Create
src/Budget.Client/src/auth/TokenSync.tsx:import { useAuth } from 'react-oidc-context'; import { useEffect } from 'react'; import { setTokenProvider } from '../api/client'; export function TokenSync() { const auth = useAuth(); useEffect(() => { setTokenProvider(() => auth.user?.access_token ?? null); }, [auth.user]); return null; } - Render
<TokenSync />inside<AuthProvider>inmain.tsx.
Phase 3 — Update AuthGuard and CallbackPage
- Update
AuthGuard.tsxto useuseAuthfromreact-oidc-context. The shape is:auth.isLoading— waiting for user to loadauth.isAuthenticated— user is signed inauth.signinRedirect()— trigger login
- Update
CallbackPage.tsx:react-oidc-contextprocesses the callback automatically; the page just needs to read?error/?error_descriptionfromuseSearchParams()and render a friendly message if present.- On success the
onSigninCallbackinmain.tsxnavigates away, so this component effectively only shows on error.
Phase 4 — Clean up
- Remove
export { userManager }from the old AuthContext (now deleted) and fix any imports that referenced it (onlyCallbackPageshould have used it). - Run
npm run build— confirm zero TypeScript errors.
Key decisions
authConfig.tsstays as-is;AuthProvideracceptsUserManagerSettingsspread directly.setTokenProviderstays inapi/client.ts—TokenSyncbridges betweenreact-oidc-contextand the fetch client without making the client depend on React.- Silent renew errors are handled automatically by
react-oidc-context's built-in event listeners — no custom wiring needed.
Files affected
package.json(new dep:react-oidc-context)src/Budget.Client/src/main.tsxsrc/Budget.Client/src/auth/AuthContext.tsx(deleted)src/Budget.Client/src/auth/AuthGuard.tsx- New:
src/Budget.Client/src/auth/TokenSync.tsx src/Budget.Client/src/pages/CallbackPage.tsx