Wrap the /user/{username} route in RequireAuth middleware #60

Closed
opened 2026-08-07 13:10:51 +02:00 by clawbot · 1 comment
Collaborator

Part of the road to 1.0 (see #33).

internal/server/routes.go setupUserRoutes() applies CSRF() to /user/{username} but not RequireAuth(). Authentication is enforced only inside HandleProfile (internal/handlers/profile.go), which is defense-by-implementation rather than defense-by-design. Every other authenticated route group (/sources, /source/{sourceID}) is wrapped in s.mw.RequireAuth(); this one should be too.

Definition of done:

  • the /user/{username} route group uses s.mw.RequireAuth()
  • an unauthenticated request is redirected to /pages/login at the middleware layer (not only by the handler)
  • existing profile behaviour (own-profile-only) and its tests still pass
Part of the road to 1.0 (see #33). `internal/server/routes.go` `setupUserRoutes()` applies `CSRF()` to `/user/{username}` but not `RequireAuth()`. Authentication is enforced only inside `HandleProfile` (`internal/handlers/profile.go`), which is defense-by-implementation rather than defense-by-design. Every other authenticated route group (`/sources`, `/source/{sourceID}`) is wrapped in `s.mw.RequireAuth()`; this one should be too. Definition of done: - the `/user/{username}` route group uses `s.mw.RequireAuth()` - an unauthenticated request is redirected to `/pages/login` at the middleware layer (not only by the handler) - existing profile behaviour (own-profile-only) and its tests still pass
clawbot added this to the 1.0.0 milestone 2026-08-07 13:10:51 +02:00
Author
Collaborator

Implementation instructions

Scope is exactly the definition of done above — one small, isolated change. Do not expand scope.

Change 1 — internal/server/routes.go, setupUserRoutes()

The /user/{username} route group currently has only r.Use(s.mw.CSRF()). Add r.Use(s.mw.RequireAuth()) immediately after the CSRF line, so auth is enforced at the middleware layer — matching /sources and /source/{sourceID}, which apply CSRF then RequireAuth. Keep the relative order: CSRF first, then RequireAuth.

Change 2 — internal/handlers/profile.go, HandleProfile

With RequireAuth in front of the route, the handler's own session.Get + IsAuthenticated + redirect-to-login branch is now dead code (the middleware guarantees an authenticated session before the handler runs). Simplify it:

  • keep reading the username and user id from the session — still needed for the own-profile-only comparison (requestedUsername != sessionUsername) and the template data
  • remove the now-unreachable "not authenticated -> redirect to /pages/login" branch
  • do NOT change the own-profile-only behaviour: a request for another user's profile must still return 403

Tests

  • keep/adjust the internal/handlers profile tests: own profile returns 200, another user's profile returns 403
  • add a test proving an unauthenticated request to /user/{username} is redirected to /pages/login by the middleware and never reaches the handler (a routing- or middleware-level test is fine)

Validation gates

  • run make fmt before committing
  • host Go is 1.25 but go.mod requires 1.26, so validate with the authoritative CI gate: docker build . must pass (it runs fmt-check, lint, test, and build). Do not skip lint; no new lint findings.

Process

  • branch from main, named issue-60-user-requireauth
  • the commit subject must end with (closes #60)
  • do not reference any AI assistant or tooling anywhere (no trailers, no mentions)
  • open a PR with base main, then post a comment on the PR describing exactly what changed and pasting the docker build . result
## Implementation instructions Scope is exactly the definition of done above — one small, isolated change. Do not expand scope. ### Change 1 — `internal/server/routes.go`, `setupUserRoutes()` The `/user/{username}` route group currently has only `r.Use(s.mw.CSRF())`. Add `r.Use(s.mw.RequireAuth())` immediately after the CSRF line, so auth is enforced at the middleware layer — matching `/sources` and `/source/{sourceID}`, which apply CSRF then RequireAuth. Keep the relative order: CSRF first, then RequireAuth. ### Change 2 — `internal/handlers/profile.go`, `HandleProfile` With `RequireAuth` in front of the route, the handler's own `session.Get` + `IsAuthenticated` + redirect-to-login branch is now dead code (the middleware guarantees an authenticated session before the handler runs). Simplify it: - keep reading the username and user id from the session — still needed for the own-profile-only comparison (`requestedUsername != sessionUsername`) and the template data - remove the now-unreachable "not authenticated -> redirect to `/pages/login`" branch - do NOT change the own-profile-only behaviour: a request for another user's profile must still return 403 ### Tests - keep/adjust the `internal/handlers` profile tests: own profile returns 200, another user's profile returns 403 - add a test proving an unauthenticated request to `/user/{username}` is redirected to `/pages/login` by the middleware and never reaches the handler (a routing- or middleware-level test is fine) ### Validation gates - run `make fmt` before committing - host Go is 1.25 but `go.mod` requires 1.26, so validate with the authoritative CI gate: `docker build .` must pass (it runs fmt-check, lint, test, and build). Do not skip lint; no new lint findings. ### Process - branch from `main`, named `issue-60-user-requireauth` - the commit subject must end with ` (closes #60)` - do not reference any AI assistant or tooling anywhere (no trailers, no mentions) - open a PR with base `main`, then post a comment on the PR describing exactly what changed and pasting the `docker build .` result
sneak closed this issue 2026-08-07 14:00:17 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#60