Question

I'm implementing basic authentication using MVC5's IAuthenticationFilter interface. My understanding is that this is now the preferred approach instead of using a DelegatingHandler. I've got it working but the www-authenticate header is not being returned in the response. This is my implementation of ChallengeAsync:

public async Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
    {
        var result = await context.Result.ExecuteAsync(cancellationToken);
        if (result.StatusCode == HttpStatusCode.Unauthorized)
        {
            result.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Basic", "realm=localhost"));
        }
    }

The header is returned if I set it in AuthenticateAsync but I think I'm supposed to set it in ChallengeAsync. Sample implementations have been hard to find.

Was it helpful?

Solution

In ChallengeAsync, set context.Result to an instance of type IHttpActionResult, like so.

public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
                                  CancellationToken cancellationToken)
{
    context.Result = new ResultWithChallenge(context.Result);
    return Task.FromResult(0);
}

Provide an implementation, like so.

public class ResultWithChallenge : IHttpActionResult
{
    private readonly IHttpActionResult next;

    public ResultWithChallenge(IHttpActionResult next)
    {
        this.next = next;
    }

    public async Task<HttpResponseMessage> ExecuteAsync(
                                CancellationToken cancellationToken)
    {
        var response = await next.ExecuteAsync(cancellationToken);
        if (response.StatusCode == HttpStatusCode.Unauthorized)
        {
            response.Headers.WwwAuthenticate.Add(
                   new AuthenticationHeaderValue("Basic", "realm=localhost"));
        }

        return response;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top