Closed seangwright closed 6 years ago
It was intentional. According to the following article, we should not use ConfigureAwait(false)
in any code that uses HttpContext.Current or builds an ASP.NET response. This makes sense, because the authorization pipeline needs to not lose the synchronization context so that it remains in the context of a single request. As such, calling .Result
or ConfigureAwait(true)
is necessary in the resource authorize attribute. You can, however, use ConfigureAwait(false)
in your code because that only configures awaiting for the function in which your await statement resides.
I would love for there to be a better alternative in the older frameworks, but at this time, the best I can think of is using asp.net core instead.
Thanks for the info. That makes sense.
The Policy AuthZ approach is real nice but our team can't transition to .NET Core just yet.
I tried a different approach to using ConfigureAwait(false)
by inheriting from the AuthorizationFilterAttribute
and the OnAuthorizationAsync
method lets me use async
/await
.
public class AuthorizeAccessAttribute : AuthorizationFilterAttribute, IAuthorizeData
{
public string Policy { get; set; }
public string ActiveAuthenticationSchemes { get; set; }
public string Roles { get; set; }
public async override Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
Guard.Against.NullOrDefault(actionContext, nameof(actionContext));
var controller = actionContext.ControllerContext.Controller as IAuthorizationController;
var user = (ClaimsPrincipal)actionContext.RequestContext.Principal;
var owinAccessor = new HttpRequestMessageOwinContextAccessor(actionContext.Request);
var helper = new AuthorizationHelper(owinAccessor);
bool isAuthorized = await helper.IsAuthorizedAsync(controller, user, this);
bool isAuthenticated = (actionContext.RequestContext.Principal?.Identity?.IsAuthenticated ?? false);
if (isAuthenticated && !isAuthorized)
{
throw new NotAuthorizedException("Resource", Policy);
}
if (!isAuthorized)
{
throw new NotAuthenticatedException("Request is not authenticated");
}
return;
}
}
Maybe it's not semantically the best approach and abuses the auth process a bit, but it seems to work as expected.
I'm running into an issue where my application deadlocks when using async/await in methods called by my
AuthorizationHandler
. If I call my async methods withConfigureAwait(false)
then the deadlock goes away.It looks like in
ResourceAuthorizeAttribute
there is a linereturn helper.IsAuthorizedAsync(controller, user, this).Result;
This is really dangerous since accessing the HttpContext anywhere downstream of this call will cause a deadlock since this line performs sync over async.
Is there an alternative to this design? Was this intentional?