You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于ASP.NET Core、Angular 5、Azure B2C的用户15分钟闲置自动登出方案咨询

Hey there! Let's walk through how to build that 15-minute idle auto-logout feature for your ASP.NET Core + Angular 5 + Azure B2C stack. This needs coordination between frontend activity tracking, backend session validation, and Azure B2C token configuration—let's break it down step by step.

Frontend (Angular 5) Implementation

The frontend is responsible for detecting user inactivity and triggering the logout flow. We'll create a dedicated service to handle this:

Step 1: Create an Idle Monitor Service

This service tracks user activity (mouse moves, key presses, etc.) and resets a timer whenever activity is detected. After 15 minutes of inactivity, it triggers logout.

import { Injectable, OnDestroy } from '@angular/core';
import { MsalService } from '@azure/msal-angular'; // Use v1.x for Angular 5 compatibility
import { HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class IdleMonitorService implements OnDestroy {
  private readonly idleTimeoutMs = 15 * 60 * 1000; // 15 minutes
  private idleTimer: any;
  private activityEvents = ['mousemove', 'keydown', 'touchstart', 'scroll'];

  constructor(
    private msalService: MsalService,
    private http: HttpClient
  ) {
    this.startIdleTimer();
    this.registerActivityListeners();
    this.syncWithOtherTabs();
  }

  private startIdleTimer(): void {
    this.clearIdleTimer();
    this.idleTimer = setTimeout(() => this.initiateLogout(), this.idleTimeoutMs);
  }

  private clearIdleTimer(): void {
    if (this.idleTimer) clearTimeout(this.idleTimer);
  }

  private registerActivityListeners(): void {
    this.activityEvents.forEach(event => {
      document.addEventListener(event, () => this.resetTimer());
    });
  }

  private resetTimer(): void {
    this.startIdleTimer();
    // Sync last activity time across tabs using localStorage
    localStorage.setItem('lastUserActivity', Date.now().toString());
  }

  private syncWithOtherTabs(): void {
    // Listen for storage changes from other tabs to reset timer
    window.addEventListener('storage', (e) => {
      if (e.key === 'lastUserActivity') {
        this.startIdleTimer();
      }
    });
  }

  private initiateLogout(): void {
    // 1. Notify backend to clear any server-side session data
    this.http.post('/api/auth/logout', {}).subscribe({
      complete: () => {
        // 2. Trigger Azure B2C logout via MSAL
        this.msalService.logout();
      }
    });
  }

  ngOnDestroy(): void {
    // Clean up listeners to avoid memory leaks
    this.clearIdleTimer();
    this.activityEvents.forEach(event => {
      document.removeEventListener(event, () => this.resetTimer());
    });
    window.removeEventListener('storage', () => {});
  }
}

Step 2: Initialize the Service

Add the service to your root component (like app.component.ts) to start monitoring as soon as the app loads:

constructor(private idleMonitor: IdleMonitorService) {}

Backend (ASP.NET Core) Setup

The backend needs to enforce idle checks to prevent users from bypassing frontend logic, and handle logout requests.

Step 1: Add an Idle Session Middleware

This middleware tracks the user's last activity time using distributed cache (ideal for Azure environments) and returns 401 if idle time exceeds 15 minutes:

public class IdleSessionMiddleware
{
    private readonly RequestDelegate _next;
    private const int IdleTimeoutMinutes = 15;

    public IdleSessionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, IDistributedCache cache)
    {
        if (context.User.Identity.IsAuthenticated)
        {
            var userId = context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            if (!string.IsNullOrEmpty(userId))
            {
                var cacheKey = $"UserLastActivity:{userId}";
                var lastActivityStr = await cache.GetStringAsync(cacheKey);

                if (!string.IsNullOrEmpty(lastActivityStr) && 
                    DateTime.TryParse(lastActivityStr, out var lastActivity) &&
                    DateTime.UtcNow.Subtract(lastActivity).TotalMinutes > IdleTimeoutMinutes)
                {
                    // User is idle - return 401 to trigger frontend logout
                    context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                    return;
                }

                // Update last activity time
                await cache.SetStringAsync(cacheKey, DateTime.UtcNow.ToString(), new DistributedCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(IdleTimeoutMinutes + 5) // Add buffer
                });
            }
        }

        await _next(context);
    }
}

Step 2: Register the Middleware

Add the middleware to your pipeline in Program.cs (or Startup.cs for older .NET versions):

app.UseMiddleware<IdleSessionMiddleware>();
// Place this AFTER authentication middleware (app.UseAuthentication())

Step 3: Add a Logout Endpoint

Create an API endpoint to clear server-side session data when logout is triggered:

[ApiController]
[Route("api/auth")]
public class AuthController : ControllerBase
{
    private readonly IDistributedCache _cache;

    public AuthController(IDistributedCache cache)
    {
        _cache = cache;
    }

    [HttpPost("logout")]
    public async Task<IActionResult> Logout()
    {
        var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        if (!string.IsNullOrEmpty(userId))
        {
            await _cache.RemoveAsync($"UserLastActivity:{userId}");
        }
        return Ok();
    }
}

Azure B2C Configuration

Ensure your Azure B2C tokens align with your idle timeout rules:

  1. Token Lifecycle Settings:

    • Go to your Azure B2C tenant → User flows → Select your login/register flow → Tokens
    • Set Access token lifetime to 15 minutes (matches your idle timeout)
    • Set Refresh token lifetime to a longer value (e.g., 24 hours) but enable Refresh token sliding window lifetime to 15 minutes—this invalidates refresh tokens if unused for 15 minutes.
  2. Logout URL Configuration:

    • In your user flow's Properties tab, set Logout URL to your app's login page. This ensures users are redirected correctly after logout.

Key Notes & Edge Cases

  • Angular 5 MSAL Compatibility: Use @azure/msal-angular v1.x (v2+ doesn't support Angular 5).
  • Distributed Cache: Use Azure Redis Cache for the backend to ensure idle tracking works across multiple server instances.
  • Test with Short Timeouts: During testing, set the idle timeout to 1 minute to speed up validation.
  • Ignore Background Tabs: If needed, add logic to pause the timer when the tab is inactive (using document.hidden property).

内容的提问来源于stack exchange,提问作者Shaikh JaniBasha Zeeshan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:51:50