Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: rotate session id proactively #1512

Merged
merged 8 commits into from
Dec 16, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions src/sessionid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export class SessionIdManager {
private _sessionIdChangedHandlers: SessionIdChangedCallback[] = []
private readonly _sessionTimeoutMs: number

// we track activity so we can end the session proactively when it has passed the idle timeout
private _enforceIdleTimeout: ReturnType<typeof setTimeout> | undefined

constructor(
config: Partial<PostHogConfig>,
persistence: PostHogPersistence,
Expand Down Expand Up @@ -162,14 +165,14 @@ export class SessionIdManager {
if (this._sessionId && this._sessionActivityTimestamp && this._sessionStartTimestamp) {
return [this._sessionActivityTimestamp, this._sessionId, this._sessionStartTimestamp]
}
const sessionId = this.persistence.props[SESSION_ID]
const sessionIdInfo = this.persistence.props[SESSION_ID]

if (isArray(sessionId) && sessionId.length === 2) {
if (isArray(sessionIdInfo) && sessionIdInfo.length === 2) {
// Storage does not yet have a session start time. Add the last activity timestamp as the start time
sessionId.push(sessionId[0])
sessionIdInfo.push(sessionIdInfo[0])
}
Comment on lines +177 to 180
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NB we can probably remove this upgrade code now but I won't do it here, a lot of time of passed since we added this


return sessionId || [0, null, 0]
return sessionIdInfo || [0, null, 0]
}

// Resets the session id by setting it to null. On the subsequent call to checkAndGetSessionAndWindowId,
Expand Down Expand Up @@ -212,7 +215,7 @@ export class SessionIdManager {
const timestamp = _timestamp || new Date().getTime()

// eslint-disable-next-line prefer-const
let [lastTimestamp, sessionId, startTimestamp] = this._getSessionId()
let [lastActivityTimestamp, sessionId, startTimestamp] = this._getSessionId()
let windowId = this._getWindowId()

const sessionPastMaximumLength =
Expand All @@ -222,7 +225,7 @@ export class SessionIdManager {

let valuesChanged = false
const noSessionId = !sessionId
const activityTimeout = !readOnly && Math.abs(timestamp - lastTimestamp) > this.sessionTimeoutMs
const activityTimeout = !readOnly && Math.abs(timestamp - lastActivityTimestamp) > this.sessionTimeoutMs
if (noSessionId || activityTimeout || sessionPastMaximumLength) {
sessionId = this._sessionIdGenerator()
windowId = this._windowIdGenerator()
Expand All @@ -238,11 +241,20 @@ export class SessionIdManager {
valuesChanged = true
}

const newTimestamp = lastTimestamp === 0 || !readOnly || sessionPastMaximumLength ? timestamp : lastTimestamp
const newActivityTimestamp =
lastActivityTimestamp === 0 || !readOnly || sessionPastMaximumLength ? timestamp : lastActivityTimestamp
const sessionStartTimestamp = startTimestamp === 0 ? new Date().getTime() : startTimestamp

this._setWindowId(windowId)
this._setSessionId(sessionId, newTimestamp, sessionStartTimestamp)
this._setSessionId(sessionId, newActivityTimestamp, sessionStartTimestamp)

if (!readOnly) {
clearTimeout(this._enforceIdleTimeout)
this._enforceIdleTimeout = setTimeout(() => {
// enforce idle timeout a little after the session timeout to ensure the session is reset even without activity
this.resetSessionId()
}, this.sessionTimeoutMs * 1.1)
}

if (valuesChanged) {
this._sessionIdChangedHandlers.forEach((handler) =>
Expand All @@ -259,7 +271,7 @@ export class SessionIdManager {
windowId,
sessionStartTimestamp,
changeReason: valuesChanged ? { noSessionId, activityTimeout, sessionPastMaximumLength } : undefined,
lastActivityTimestamp: lastTimestamp,
lastActivityTimestamp: lastActivityTimestamp,
}
}
}
Loading