Implement token-based sessions
Changes
Follow-up to https://github.com/plausible/analytics/pull/4452 implementing token-based sessions.
- A new table is added for storing sessions called
user_sessionsand used byAuth.UserSessionschema - The session struct stores user reference, token (randomly generated on creation),
last_used_atandtimeout_attimestamps - Inactive session timeout is kept at 14 days, like before, just managed server-side
- New user sessions refresh is managed by a new plug,
UserSessionTouchwhich also converts existing legacy sessions to new ones on the go - There's a
CleanUserSessionsbackground job cleaning timed out sessions with an additional grace period of 7 days, just in case (sessions, when retrieved are always filtered by timeout, so that's not an issue) - Retrievals of legacy sessions is logged with a warning. Logs will be scanned for occurrences to determine whether rate of legacy sessions goes down towards zero during/after 14 day period as expected
- Device name is detected using logic largely copied from
Ingestion.Eventpipeline. I have decided to not DRY these as they serve very different purposes.
TODO
- [x] properly refresh valid and dispose of expired sessions
- [x] instrument retrievals of legacy session cookie (accomplished with simple logging)
- [x] more tests
- [ ] extract migration to a different PR (may be done post-review)
Tests
- [x] Automated tests have been added
Changelog
- [x] Entry has been added to changelog
Documentation
- [x] This change does not need a documentation update
Dark mode
- [x] This PR does not change the UI
| Preview environment👷🏼♀️🏗️ |
|---|
| PR-4463 |
@ukutaht I have revised session retrieval and modified logic so that session, user and last subscription are always fetched in a single query. I have also modified plug pipelines interacting with session to ensure they don't refetch the session or user unless necessary.
By the way, I have noticed that our external API endpoints (/api/event included) have :fetch_session and AuthPlug in their pipeline - I have removed both as none of those endpoints need the session (I'll do some double-checking for that still).
This limits the number of session related queries to minimum. When I open funnel settings, I can see 2 SELECTs of user session (one for dead view and one for live view, we can't get around that), and one UPDATE for user_session (via UserSessionTouch). All else is related to validating site access permission (user role, site membership etc.). If we want to address those, I'd opt for doing that in a separate PR.
@aerosol @ukutaht all feedback so far applied and PR ready for re-review.