Adding Authentication to React AppsEntry 10 of 11
Security Notes and Project Structure
Practical security limits of client-side auth, and where the auth pieces live.
Notes
- Client-side checks are UX, not security. Hiding buttons and redirecting from routes can be bypassed. The backend must validate the token on every protected request.
localStorageis readable by any script on the page, so an XSS vulnerability can steal the token. Alternatives:httpOnlycookies set by the server: JavaScript can't read them, and the browser sends them automatically (requires CSRF protection).- Short-lived access token in memory + refresh token in an
httpOnlycookie: the common production pattern.
- Never log tokens or put them in URLs.
- Match the frontend expiration to the backend's, or decode the JWT's
expclaim instead of hardcoding a duration.
Code compare
src/├── App.tsx // routes: root (id, tokenLoader), auth, logout, protected loaders├── util/│ └── auth.ts // store/get/clear token, tokenLoader, checkAuthLoader├── services/│ ├── auth.ts // authenticate()│ ├── http.ts // authFetch()│ └── events.ts├── pages/│ ├── Root.tsx // auto logout timer│ ├── Authentication.tsx // + action│ └── Logout.ts // action only└── components/ ├── AuthForm.tsx └── MainNavigation.tsx // conditional linkssrc/app/├── app.config.ts // provideHttpClient(withInterceptors([authInterceptor]))├── app.routes.ts├── core/│ ├── auth/│ │ ├── auth.service.ts // token signal, login/signup, logout, timer│ │ ├── auth.guard.ts│ │ ├── auth.interceptor.ts│ │ └── auth.component.ts│ └── layout/main-navigation.component.ts└── events/ └── events.routes.ts // canActivate: [authGuard]