danielmichaels / danielmichaels/gecko
Rate-limit auth endpoints (login / signup / invite-accept)
- Dominant language
- Go
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
The unauthenticated auth endpoints have **no rate limiting**, leaving them open to password brute-force and email enumeration.
## Evidence
- `internal/server/routes.go` — `/api/auth/login`, `/api/auth/signup`, `/api/invitations/accept` are registered with no throttle.
- `internal/server/server.go` — the middleware chain is `Recoverer`, `RealIP`, `traceMiddleware`, `compressExceptSSE`, `httplog`, `recordSSEStatus`. No rate limiter.
- A `PgRateLimiter` exists for the DNS resolver layer (`internal/dnsclient`) but nothing equivalent guards the HTTP API.
## Why it matters
- **Brute-force:** unlimited `/login` attempts against any known email.
- **Enumeration:** signup/invite-accept responses can distinguish valid vs invalid accounts.
- Also protects the browser UI login (same service path).
## Design considerations (flag before implementing)
- **Per-IP vs per-account:** per-IP throttling is simplest but evadable behind NAT/proxies; per-account (email) protects a specific user but enables a lockout-DoS. Consider both with different windows.
- **Store:** in-memory limiter (e.g. `chi`/`tollbooth`/`golang.org/x/time/rate`) is simplest but per-instance — won't hold across a horizontally-scaled deployment. A Postgres-backed limiter (reuse the `PgRateLimiter` pattern) is fleet-wide consistent but adds DB load on every auth hit. **Flag this CAP/cost trade-off explicitly when picking an approach.**
- `RealIP` is already in the chain, so the client IP is available — but confirm it's only trusted behind a known proxy (header spoofing otherwise).
## Acceptance criteria
- [ ] Login/signup/invite-accept are rate-limited; limits are configurable via env (`internal/config`).
- [ ] Exceeding the limit returns `429` with a `Retry-After`.
- [ ] Decision on per-IP vs per-account documented in the PR.
- [ ] Tests covering the limit boundary.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with internal/server/routes.go and internal/server/server.go to trace the three auth endpoints and current middleware chain, then inspect internal/config and the existing PgRateLimiter pattern in internal/dnsclient. Before implementation, document the per-IP versus per-account and in-memory versus Postgres-backed decision; done means configurable limits, 429 responses with Retry-After, and boundary tests for login, signup, and invite-accept.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, postgresql
- Domain
- api, authentication, backend, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100