Course contentsShow
← C#
Lesson 1222 of 1,90811. Identity, Security, and ClaimsFree lesson

Authorization for Long-Running Tasks

Handle permission validation within background worker threads and message queues.

In this lesson, you will learn how to maintain consistent security boundaries when offloading work to background threads or message queues.

The Challenge of Context Loss

When a user initiates a request in a web controller, the HttpContext provides immediate access to their ClaimsPrincipal. However, when that request triggers a long-running task—like generating a complex report or processing a video file—the original HttpContext is disposed of as soon as the response is sent. If your background worker simply "takes over" the task, it effectively loses the user's identity, creating a security gap where the background thread might perform actions it isn't authorized to complete.

Capturing Identity for Background Work

To authorize background operations, you must capture the security context before the request finishes. Since you cannot pass the HttpContext itself across threads, you must extract the necessary claims and pass them as data.

Consider a message queue scenario where you need to verify if a user has the ReportGenerator policy before they can trigger an export:

// Inside the Controller: Capture the identity
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var claims = User.Claims.Select(c => new { c.Type, c.Value }).ToList();

// Queue the background job with the identity payload
await _messageQueue.EnqueueAsync(new ReportJob { 
    UserId = userId, 
    Claims = claims 
});

Within your background worker, you must re-instantiate a ClaimsPrincipal using the captured data. You then perform a manual authorization check using the IAuthorizationService—the same service used in your middleware—before executing the logic:

// Inside the Background Worker
var identity = new ClaimsIdentity(job.Claims.Select(c => new Claim(c.Type, c.Value)));
var principal = new ClaimsPrincipal(identity);

// Perform policy evaluation before starting the task
var result = await _authService.AuthorizeAsync(principal, "ReportGeneratorPolicy");

if (result.Succeeded) {
    await ProcessReportAsync();
} else {
    throw new UnauthorizedAccessException("Identity lacks required permissions for background task.");
}

By explicitly re-hydrating the identity and re-evaluating the policy inside the background thread, you ensure that the authorization decision is just as strict for asynchronous work as it is for synchronous web requests.

Key Takeaway: Never assume the background worker has authority; manually capture identity claims at the start and re-evaluate authorization policies before executing long-running tasks.