sachin
sachin

Reputation: 646

Sending json response using Authentication filter in Web api controller?

I have an authentication filter in my controller

[ArcGISAuthentication]

I have defined the filter like below

public class ArcGISAuthenticationAttribute : Attribute, IAuthenticationFilter
{
    public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
    {
        return Task.Run(async () =>
        {
            var queryParameters = HttpUtility.ParseQueryString(context.Request.RequestUri.Query);
            var token = queryParameters["token"];
            if (!string.IsNullOrWhiteSpace(token))
            {
                var userInfo = await CommunityManager.GetUserInfoAsync(token);
                context.Principal = new ArcGISUserPrincipal(userInfo, token);
                context.Request.SetUserPrincipal(context.Principal);
            }
            else{
                //What shoudld I do here to send a json response
            }
        });
    }

    public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
    {
        return Task.Run(() => { });
    }

    public ArcGISAuthenticationAttribute()
    {

    }
}

The problem is I want to send a json repsonse when the authentication fail. As in the else statement in the AuthenticateAsync above.

How can I do this?

Upvotes: 2

Views: 1908

Answers (1)

Nkosi
Nkosi

Reputation: 247088

Create a custom error result

public class ErrorResult : IHttpActionResult {
    public ErrorResult(HttpRequestMessage request, string message, HttpStatusCode status = HttpStatusCode.InternalServerError, string reasonPhrase = "Internal Server Error") {
        ReasonPhrase = reasonPhrase;
        Request = request;
        Message = message;
        Status = status;
    }

    public HttpStatusCode Status { get; private set; }

    public string ReasonPhrase { get; private set; }

    public string Message { get; private set; }

    public HttpRequestMessage Request { get; private set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) {
        return Task.FromResult(Execute());
    }

    private HttpResponseMessage Execute() {
        var status = Status;
        var responseBody = new Models.envelope {
            meta = new Models.metadata {
                code = (int)status,
                type = ReasonPhrase ?? status.ToString().ToCamelCase(),
                message = Message
            },
            data = null
        };
        var response = Request.CreateResponse(status, responseBody);
        response.RequestMessage = Request;
        response.ReasonPhrase = ReasonPhrase;
        return response;
    }
}

and set it to the context.Error property

if (!string.IsNullOrWhiteSpace(token))
{
    var userInfo = await CommunityManager.GetUserInfoAsync(token);
    context.Principal = new ArcGISUserPrincipal(userInfo, token);
    context.Request.SetUserPrincipal(context.Principal);
}
else
{
    context.Error = new ErrorResult(context.Request, "Some message to return");
}

In the Execute of the result you can set the response message to JSON or let the content negotiator determine what media type to return based on request headers.

Upvotes: 3

Related Questions