ASP.NET Core Identity 자동 로그아웃 및 세션 타임아웃 구현
이 문서는 ASP.NET Core Identity 기반 애플리케이션에서 자동 로그아웃 기능을 구현하는 방법을 설명하고 있습니다.
Blazor Server, MVC, Razor Pages 환경 모두에서 안정적으로 동작하도록 구성되어 있으며, 서버 세션 만료 감지와 클라이언트 무반응(inactivity) 감지를 함께 적용하는 것이 특징입니다.
본 가이드는 다음과 같은 요구 사항을 충족하기 위해 설계되었습니다.
- 사용자가 일정 시간 동안 아무런 활동을 하지 않을 경우 자동 로그아웃이 수행됩니다.
- 사용자가 활동을 지속하더라도 서버 세션이 만료되면 자동 로그아웃이 수행됩니다.
- Blazor Server의 SignalR 통신이나 SlidingExpiration 때문에 세션이 예상치 못하게 연장되는 문제를 방지합니다.
- Identity 로그인 페이지에서는 자동 체크가 비활성화됩니다.
1. 전체 구조 개요
자동 로그아웃 기능은 크게 두 가지 방식으로 구성되어 있습니다.
1) 클라이언트 무반응 감지
사용자가 마우스 이동, 클릭, 키보드 입력, 화면 스크롤, 화면 터치 등 어떠한 활동도 하지 않으면 일정 시간이 지난 뒤 자동으로 로그아웃됩니다.
이 예제에서는 25분으로 설정되어 있으며, 필요에 따라 조정할 수 있습니다.
2) 서버 세션 만료 감지
ASP.NET Core Identity의 인증 쿠키 만료 시간을 30분으로 설정합니다.
그리고 31분 주기로 /auth/ping 엔드포인트를 호출하여, 서버에서 세션이 만료된 경우 401 상태를 반환하도록 구성합니다.
세션 만료 후 첫 ping 시점에서 로그아웃이 감지됩니다.
이 두 방식이 함께 동작하기 때문에 보다 안정적이고 정확한 자동 로그아웃 시스템을 구성할 수 있습니다.
2. 클라이언트 자동 로그아웃 스크립트
다음 스크립트를 wwwroot/js/az-auth-ping.js 파일에 저장합니다.
(function () {
// 로그인 또는 공개 페이지에서는 자동 체크를 수행하지 않습니다.
var path = window.location.pathname.toLowerCase();
if (
path.startsWith('/identity/account/login') ||
path.startsWith('/identity/account/register') ||
path.startsWith('/identity/account/forgotpassword') ||
path.startsWith('/identity/account/resetpassword')
) {
return;
}
// 서버 세션 만료 감지를 위한 ping 호출
setInterval(function () {
fetch('/auth/ping')
.then(r => {
if (r.status === 401) {
const currentUrl = window.location.pathname + window.location.search;
const loginUrl = "/Identity/Account/Login?returnUrl=" + encodeURIComponent(currentUrl);
window.location.href = loginUrl;
}
})
.catch(err => {
console.log("Ping request failed", err);
});
}, 31 * 60 * 1000);
// 클라이언트 무반응 감지
var INACTIVITY_LIMIT = 25 * 60 * 1000;
var inactivityTimer = null;
function resetInactivityTimer() {
if (inactivityTimer) {
clearTimeout(inactivityTimer);
}
inactivityTimer = setTimeout(function () {
const currentUrl = window.location.pathname + window.location.search;
const loginUrl = "/Identity/Account/Login?returnUrl=" + encodeURIComponent(currentUrl);
window.location.href = loginUrl;
}, INACTIVITY_LIMIT);
}
// 사용자 활동 이벤트에 따라 타이머를 초기화합니다.
['click', 'mousemove', 'keydown', 'scroll', 'touchstart']
.forEach(function (eventName) {
document.addEventListener(eventName, resetInactivityTimer, true);
});
resetInactivityTimer();
})();
3. ASP.NET Core Identity 쿠키 설정
Program.cs 또는 Startup.cs에서 다음과 같이 Identity 쿠키 동작을 설정합니다.
builder.Services.ConfigureApplicationCookie(options =>
{
options.AccessDeniedPath = "/Identity/Account/AccessDenied";
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
options.LoginPath = "/Identity/Account/Login";
options.LogoutPath = "/Identity/Account/Logout";
options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
options.SlidingExpiration = true;
// /auth/ping 요청은 리디렉션하지 않고 401 상태만 반환합니다.
options.Events.OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/auth/ping"))
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return Task.CompletedTask;
}
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
// /auth/ping 요청은 SlidingExpiration의 쿠키 갱신을 유발하지 않도록 합니다.
options.Events.OnValidatePrincipal = context =>
{
if (context.Request.Path.StartsWithSegments("/auth/ping"))
{
context.ShouldRenew = false;
}
return Task.CompletedTask;
};
});
이 설정을 통해 /auth/ping 호출이 인증 쿠키 갱신을 유발하지 않으며, 사용자 활동 여부와 관계없이 세션 만료 시간을 정확하게 유지할 수 있습니다.
4. /auth/ping 컨트롤러
서버에서 인증 상태를 확인하기 위한 간단한 엔드포인트는 다음과 같습니다.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Zero.Controllers
{
[Authorize]
public class AuthController : Controller
{
[HttpGet("/auth/ping")]
public IActionResult Ping()
{
return Ok();
}
}
}
세션이 이미 만료된 경우 실행되기 전에 401 Unauthorized가 반환됩니다.
5. 레이아웃에 스크립트 삽입
사이트 공통 레이아웃 파일에 다음 스크립트를 포함합니다.
Blazor Server
Pages/_Host.cshtml
MVC 또는 Razor Pages
Views/Shared/_Layout.cshtml
<script src="~/js/az-auth-ping.js"></script>
6. 마무리
이 문서에서 설명한 자동 로그아웃 구성은 클라이언트와 서버의 관점에서 모두 세션 만료를 관리하는 안정적인 방법입니다. 이 방식은 다음과 같은 장점이 있습니다.
- 사용자가 아무런 활동을 하지 않을 경우 빠르게 자동 로그아웃됩니다.
- 사용자가 계속 활동하더라도 서버 세션 만료 후 자동 로그아웃이 보장됩니다.
- SlidingExpiration 때문에 세션이 연장되는 상황을 효과적으로 방지할 수 있습니다.
- Blazor Server 및 MVC 혼합 구조에서도 안전하게 사용할 수 있습니다.