This document describes authentication, route protection, and how the front-end reacts to backend errors. The application is a browser SPA; all real authorization is enforced by the backend — the front-end controls are for UX and defense in depth only.
Authentication is cookie/session based. The Axios instance
(src/utilities/http.js) is created with withCredentials: true, so the
session cookie set by the backend is sent on every request.
The login flow lives in src/stores/session.store.js:
login(credentials)issuesPOST auth/loginwith anAuthorization: Basic <base64(username:password)>header; the backend responds by setting the session cookie.- On success it calls
fetchUserInfo()(GET auth/me) to load the current user and marks the session valid. logout()callsPOST auth/logout, clears local user state, and redirects to the login route regardless of the request outcome.isSessionValid()returns the cached validity, or falls back toauth/mewhen the state is unknown (e.g. after a page reload).
Credentials are never persisted client-side; only the derived user (name,
email) and a sessionValid flag are kept in the Pinia store.
The global guard in src/router/index.js protects all routes by default:
router.beforeEach((to, from, next) => {
const { isSessionValid } = useSessionStore()
const isPublicRoute = to.matched.some((route) => route.meta.public)
if (!isPublicRoute && !isSessionValid()) {
next({ name: 'login', query: { redirect: to.path } })
return
}
next()
})To make a route reachable without a session, mark it meta: { public: true }
(see src/router/public.routes.js).
The response interceptor in src/utilities/http.js maps backend errors to
either a toast notification (useNotification) or a redirect to an error page
(userErrorHandler). Requests whose URL includes auth/me or accounts/ are
ignored by the interceptor and rejected so the caller can handle them.
| Status | Behavior |
|---|---|
400 Bad Request |
Warn toast with the localized backend message |
409 Conflict |
Warn toast listing the conflicting fields |
422 Unprocessable Entity |
Warn toast |
401 Unauthorized |
No-op (TODO: should log out / redirect to login) |
403 Forbidden |
Redirect to the 403 page |
500 Server Error |
Redirect to the 500 page |
| other / unknown | Generic error toast |
network failure (ERR_NETWORK) |
Connection-failure toast |
Known gap:
401is currently a no-op (an explicitTODOin the code), so an expired session is not actively handled at the interceptor level — the route guard catches it on the next navigation instead. There is no dedicated404branch. See testing.md for related hardening work.
No secrets are stored in the repository. The committed .env.development and
.env.production files contain only the backend base URL and a request-logging
flag — see development.md. Real
deployments should provide VITE_API_URL via the deployment environment rather
than relying on the checked-in defaults.