Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Security, Thread.CurrentPrincipal, and ConfigureAwait(false)

Would using Thread.CurrentPrincipal's claims in a referenced library that uses ConfigureAwait(false) pose any problems or will the flowing of ExecutionContext's logical call context take care of me there? (my reading and testing so far indicates that it will).

Example WebAPI Controller Action:

[CustomAuthorizeThatSetsCurrentUsersClaimsToThreadCurrentContextAndHttpContextCurrentUser]
public async Task<Order> Get(int orderId)
{
    return await _orderBusinessLogicLibrary.LoadAsync(orderId); // defaults to .ConfigureAwait(true)
}

Example load functions from external, referenced library:

[ClaimsPrincipalPermission(
    SecurityAction.Demand,
    Operation="Read",
    Resource="Orders")]
[ClaimsPrincipalPermission(
    SecurityAction.Demand,
    Operation="Read",
    Resource="OrderItems")]
public async Task<Order> Load(int orderId)
{
    var order = await _repository.LoadOrderAsync(orderId).ConfigureAwait(false);

    // here's the key line.. assuming this lower-level function is also imposing
    // security constraints in the same way this method does, would
    // Thread.CurrentPrincipal still be correct inside the function below?
    order.Items = await _repository.LoadOrderItemsAsync(orderId).ConfigureAwait(false);
    return order;
}

Also, the answer can't be "well don't use ConfigureAwait(false) then!". That can cause other problems such as deadlock (Don't Block on Async Code).

like image 826
Madeline Trotter Avatar asked Dec 09 '13 20:12

Madeline Trotter


People also ask

What is. ConfigureAwait false?

Calling ConfigureAwait(false) after the task means that we do not care if the code after the await, runs on the captured context or not. In the output console, “True” will be printed since the synchronization context is not kept.

When to not use ConfigureAwait false?

If the await task. ConfigureAwait(false) involves a task that's already completed by the time it's awaited (which is actually incredibly common), then the ConfigureAwait(false) will be meaningless, as the thread continues to execute code in the method after this and still in the same context that was there previously.

What is ConfigureAwait true?

A situation to use ConfigureAwait(true) is when performing await in a lock, or using any other context/thread specific resources. This requires a synchronization context, which you will have to create, unless you are using Windows Forms or WPF, which automatically create a UI synchronization context.

What does ConfigureAwait mean?

ConfigureAwait(continueOnCapturedContext: false) is used to avoid forcing the callback to be invoked on the original context or scheduler. This has a few benefits: Improving performance.


1 Answers

From my tests, it appears that Thread.CurrentPrincipal will flow correctly, even if you use ConfigureAwait(false). The following WebAPI code sets the principal and then blocks on an async call, forcing another thread to resume the async method. That other thread does inherit the correct principal.

private async Task<string> Async()
{
    await Task.Delay(1000).ConfigureAwait(false);
    return "Thread " + Thread.CurrentThread.ManagedThreadId + ": " + Thread.CurrentPrincipal.Identity.Name + "\n";
}

public string Get(int id)
{
    var user = new ClaimsPrincipal(new ClaimsIdentity(
        new[]
        {
            new Claim(ClaimTypes.Name, "Bob"),
        }
    ));
    HttpContext.Current.User = user;
    Thread.CurrentPrincipal = user;

    var ret = "Thread " + Thread.CurrentThread.ManagedThreadId + ": " + Thread.CurrentPrincipal.Identity.Name + "\n";

    ret += Async().Result;

    return ret;
}

When I run this code on a new instance of IISExpress, I get:

"Thread 7: Bob\nThread 6: Bob\n"

However, I should point out that using ConfigureAwait(false) to avoid deadlock is not recommended. This is especially true on ASP.NET. If at all possible, use ConfigureAwait(false) and also use async all the way. Note that WebAPI is a fully-async stack and you should be able to do this.

like image 81
Stephen Cleary Avatar answered Oct 27 '22 21:10

Stephen Cleary