ASPNETZERO + Angular
Session timeout is only considering mouse moments and keyboard input. But when locks the PC/laptop (or ven not active tab) and comes back after timeout period, session is still active. Can you guys suggest changes to make to make it SOC 2 compliance like session expires for device and muti tab scenario.
1 Answer(s)
-
0
Hi @mmukkara
Out of the box, session timeout is handled almost entirely on the frontend and only tracks user interaction events such as mouse and keyboard input. As a result:
- Locking the device
- Switching browser tabs
- Minimizing the browser
- Leaving the tab inactive for long periods
does not reliably invalidate the session, which is not SOC 2 compliant.
Below is a practical and production ready approach to fix this.
Current Behavior
Frontend (Angular)
session-timeout.component.tslistens only to:mousemovemousedownclickscrollkeypress
Last activity timestamp is stored in
localStorageA client-side timer checks timeout every second
No awareness of tab visibility, window focus, or device lock
Detect inactive tabs / minimized windows
Use Page Visibility API:
fromEvent(document, 'visibilitychange') .pipe(takeUntil(this.destroy$)) .subscribe(() => { if (document.hidden) { this.pauseSession(); } else { this.resumeSession(); } });When the tab becomes visible again, immediately check timeout:
private resumeSession(): void { const lastActivity = this.getLastActivityTime(); if (Date.now() - lastActivity > this.timeOutSecond * 1000) { this.sessionTimeOutModal().done(); } }Add absolute session timeout
Even if the user is active, force logout after a fixed duration:
private absoluteTimeout = 8 * 60 * 60 * 1000; // 8 hours private sessionStartTime = Date.now(); private checkAbsoluteTimeout(): void { if (Date.now() - this.sessionStartTime > this.absoluteTimeout) { this.sessionTimeOutModal().done(); } }Backend Improvements
Shorten token lifetimes
public static TimeSpan AccessTokenExpiration = TimeSpan.FromMinutes(30); public static TimeSpan RefreshTokenExpiration = TimeSpan.FromDays(7);This alone dramatically improves security posture.
Enforce idle timeout on the server
Implement idle validation during JWT processing:
private void ValidateIdleTimeout(ClaimsPrincipal principal) { var lastActivityClaim = principal.Claims .FirstOrDefault(c => c.Type == "LastActivity"); if (lastActivityClaim != null) { var lastActivity = DateTime.Parse(lastActivityClaim.Value); var idleTimeout = TimeSpan.FromMinutes(30); if (DateTime.UtcNow - lastActivity > idleTimeout) { throw new SecurityTokenException("Session expired due to inactivity"); } } }Update last activity on every request
Use middleware or an action filter:
public class LastActivityMiddleware { public async Task InvokeAsync(HttpContext context) { if (context.User.Identity?.IsAuthenticated == true) { var userId = context.User.GetUserId(); await _cacheManager .GetCache("UserActivity") .SetAsync($"LastActivity_{userId}", DateTime.UtcNow); } await _next(context); } }I’ve also created an issue for this. We will evaluate this matter separately. I hope these suggestions are helpful. Please feel free to ask if you have any questions.
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image)