4.0 KiB
id, title, status, assignee, created_date, updated_date, labels, dependencies, references, priority
| id | title | status | assignee | created_date | updated_date | labels | dependencies | references | priority | ||
|---|---|---|---|---|---|---|---|---|---|---|---|
| ML-5 | Document Last.fm OAuth callback trust boundary | Done |
|
2026-04-20 08:48 | 2026-04-24 07:04 |
|
low |
Description
GitHub: created 2026-04-16 · updated 2026-04-16
Summary
GET /auth/last_fm/callback?token=X is unauthenticated by design (OAuth flow requires it) but triggers storage of a session key in the encrypted secrets table. The trust model is not captured in comments, so future reviewers may re-flag it.
Evidence
lib/music_library_web/controllers/last_fm_controller.ex:7lib/music_library_web/router.ex:55(route outside:logged_inpipe)
Attack surface: cannot forge a valid token (Last.fm validates), but a malicious caller could consume LastFm.get_session/1 rate-limit quota. Acceptable given the threat model.
Fix
Add a short @moduledoc or inline comment in last_fm_controller.ex explaining:
- Why this endpoint is unauthenticated (OAuth flow cannot carry session cookies across the Last.fm redirect)
- What protects it (Last.fm-validated token, rate limiter, single-user scope)
- What the failure modes look like (invalid token → store nothing, error logged)
Similarly in router.ex:55, a brief comment noting the deliberate exception from :logged_in.
Acceptance Criteria
- #1 last_fm_controller.ex has a comment documenting the trust boundary
- #2 router.ex:55 notes the deliberate pipeline exemption
Implementation Plan
Implementation Plan
-
lib/music_library_web/controllers/last_fm_controller.ex— add@moduledoccovering:- Why unauthenticated: OAuth redirect from Last.fm cannot carry session cookies across third-party redirect.
- What protects it: Last.fm validates the
tokenviaLastFm.get_session/1; the call is rate-limited at theReqlayer (Req.RateLimiter, 500ms/req); this is a single-user deployment. - Failure mode: invalid/forged tokens cause
get_session/1to return{:error, _}; nothing is written tosecrets, an error toast is shown, and the Req-layer error is logged.
-
lib/music_library_web/router.ex:55— add a brief comment above the route noting deliberate exemption from the:logged_inpipeline (with pointer to the controller moduledoc for details). -
Run
mise run dev:precommitto verify formatting, credo (includingModuleDocrule), sobelow, and tests still pass.
Notes
- Controllers are excluded from the
Credo.Check.Readability.ModuleDocregex in.credo.exs, so@moduledochere is optional for lint purposes — using it is a deliberate choice for this security-sensitive module. - No test changes required (documentation-only).
Final Summary
Summary
Documented the Last.fm OAuth callback trust boundary in two places:
lib/music_library_web/controllers/last_fm_controller.ex— added@moduledocexplaining why the endpoint is unauthenticated (OAuth redirect from Last.fm cannot carry session cookies), what protects it (Last.fm-validated token,Req.RateLimiterbounding quota burn, single-user deployment), and the failure mode (invalid token → nothing stored, error toast shown).lib/music_library_web/router.ex— added a comment above the/auth/last_fm/callbackroute noting the deliberate exemption from the:logged_inpipeline, with a pointer to the controller moduledoc for the full trust boundary.
Verification
mise run dev:precommit passes: credo, sobelow, format, translations, unused deps, and tests (827 passed, 43 doctests).
Notes
Controllers are excluded from the Credo.Check.Readability.ModuleDoc regex in .credo.exs, so the @moduledoc here is a deliberate choice for a security-sensitive module, not a lint requirement.