owltide/docs/dev/sessions.md
Hornwitser 3f492edea2 Separate rotation and expiry of sessions
If a session is rotate in the middle of a server side rendering then
some random portions of requests made on the server side will fail with
a session taken error as the server is not going to update the cookies
of the client during these requests.

To avoid this pitfall extend the expiry time of sessions to be 10
seconds after the session has been rotated.  This is accomplished by
introducing a new timestamp on sessions called the rotateAt at time
alongside the expiresAt time.  Sessions used after rotateAt that haven't
been rotated get rotated into a new session and the existing session
gets the expiresAt time set to 10 seconds in the future.  Sessions that
are past the expiredAt time have no access.

This makes the logic around session expiry simpler, and also makes it
possible to audit when a session got rotated, and to mark sessions as
expired without a chance to rotate to a new session without having to
resort to a finished flag.
2025-07-09 14:54:54 +02:00

1.9 KiB

Sessions

When a user creates a new account or logs in to an existing account a session is created on the server and linked to the user's browser via a session cookie. This cookie contains a unique identifier along with a HMAC signature created using the server's cookie secret key. Since this unique identifier stored on the user's device is a technical requirement to securely do what the user is requesting the user's consent to its storage can be assumed.

Sessions have three future times associated with them: The rotates time is the point in time after the session will be recreated and the cookie reassigned, the expiry time is the point in time after which use of the session will be rejected, and the discard time is when the session is deleted from both the client and the server. The rotation time is short, by default 1 hour, while the discard time is long, by default 2 weeks.

When a request is made to a session that's past the rotates time a new session is created to replace the existing one, the expiry time is set on the existing session to 10 seconds later, and the session cookie is updated with the new session. The purpose of this is to reduce the time window a stolen session can be used in without being detected. If a request is made using a session that has expired the server responds with a message saying the "session has been taken". The reason for having the session expire 10 seconds after the rotation is to prevent race conditions from triggering the session taken error.

Sessions are created for a limited timespan, purpose and access level, and expires after the timespan is over, the purpose is fulfilled or the access level changes. For example if the user's account is promoted from regular to crew the session will no longer be valid and will be recreated as a new session with the new access level on the next request.