Ok so bear with me this might take some explaining, i have a simple Account controller thus;
[RoutePrefix("api/account")]
[Authorize]
[HmacAuthentication]
public class AccountController : ApiController
{
public async Task<IHttpActionResult> Register(UserModel userModel)
{
if (!this.ModelState.IsValid)
{
return this.BadRequest(this.ModelState);
}
IdentityResult result = await this._userService.RegisterUser(userModel);
var errorResult = this.GetErrorResult(result);
if (errorResult != null)
{
return errorResult;
}
return this.Ok();
}
}
The HmacAuthentication attribute is here:
public class HmacAuthenticationAttribute : Attribute, IAuthenticationFilter
{
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
...
var isValid = this.IsValidRequest(req, appId, incomingBase64Signature, nonce, requestTimeStamp);
if (isValid.Result)
{
...
}
...
}
private async Task<bool> IsValidRequest(
HttpRequestMessage req,
string appId,
string incomingBase64Signature,
string nonce,
string requestTimeStamp)
{
...
var user = await this.UserService.FindUser(userId); // this never gets a return value
...
}
}
The method called in the UserService
is this:
public async Task<ApplicationUserModel> FindUser(int id)
{
var user = await this._userBusiness.FindAsync(id);
return this.MapToModel(user);
}
and in the business class is this:
public async Task<ApplicationUser> FindAsync(int id)
{
var result = await this._userManager.FindByIdAsync(id);
return result;
}
The problem that i am facing is that when the Register method is called the HmacAuthentication attribute fires and the AuthenticateAsync filter method executes. The call in IsValidRequest
to lookup a user is never actually getting a return value, if i try a request through postman it never completes.
Can anyone help with this please?
public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
...
var isValid = await this.IsValidRequest(req, appId, incomingBase64Signature, nonce, requestTimeStamp);
if (isValid)
{
...
}
...
}
As the compiler suggested, you can only use the await
keyword inside of a method marked as async
. So I have updated the signature for AuthenticateAsync accordingly. Also note that you can just check isValid
now instead of doing isValid.Result
since the value of the boolean will be available past the await line.
This can be a little confusing as the interface for IAuthenticationFilter doesn't specify async (interfaces can't, they can only indicate that the method will return a Task). It is up to the implementer to determine whether or not the method will simply return the task or will supply an async so that values can be awaited inside the method body.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With