Question

I'm not sure if I'm doing something wrong or there's a bug of some kind. If it is a bug, then I'd think this would have cropped up immediately. Either way:

I'm using the extension method RequiresAuthentication from here:

https://github.com/NancyFx/Nancy/blob/9d3c650575cba109e620ab163f4fda26a0536036/src/Nancy/Security/ModuleSecurity.cs

Which uses SecurityHooks

https://github.com/NancyFx/Nancy/blob/9d3c650575cba109e620ab163f4fda26a0536036/src/Nancy/Security/SecurityHooks.cs

Or the code specifically:

public static void RequiresAuthentication(this INancyModule module)
{
    module.AddBeforeHookOrExecute(SecurityHooks.RequiresAuthentication(), "Requires Authentication");
}

SecurityHooks:

public static Func<NancyContext, Response> RequiresAuthentication()
{
    return UnauthorizedIfNot(ctx => ctx.CurrentUser.IsAuthenticated());
}

private static Func<NancyContext, Response> UnauthorizedIfNot(Func<NancyContext, bool> test)
{
    return HttpStatusCodeIfNot(HttpStatusCode.Unauthorized, test);
}

private static Func<NancyContext, Response> HttpStatusCodeIfNot(HttpStatusCode statusCode, Func<NancyContext, bool> test)
 {
        return (ctx) =>
        {
            Response response = null;
            if (!test(ctx))
            {
                response = new Response { StatusCode = statusCode };
            }

            return response;
        };
    }

As you can see HttpStatusCode.Unauthorized should be returned if the user isn't authenticated. Seems easy enough. When I make an AJAX call to a route like:

Post["/comment/flag/{Id}"] = s =>
{
            this.RequiresAuthentication();
            return new IdResponse { Id = commentRepo.FlagComment(Context.CurrentUser.UserName, s.Id) };
};

I'm getting back a 303, which then redirects to the login URL with a 200. Yucky. Not expected at all.

Just to make sure I'm not totally crazy, I did the following and it worked fine:

Post["/comment/{Id}"] = s =>
        {
            if ((Context.CurrentUser == null) ||
                    String.IsNullOrWhiteSpace(Context.CurrentUser.UserName))
            {
                return HttpStatusCode.Forbidden;
            }

            var req = this.Bind<CommentRequest>();
            return commentRepo.AddComment(Context.CurrentUser.UserName, s.Id, req.Comment);
        };

This returns the expected 403. But who wants to paste this all over the place...not me. I'm trying to figure out how to write my own thing that executes before the route is run but I'm new to Nancy.

Curiously, if I change the:

return HttpStatusCode.Forbidden; 

into a

return new Response { StatusCode = HttpStatusCode.Forbidden };

Then I get the 303 and 200 responses again. Something seems broken. Can anyone give me some insight or an answer of what I'm doing wrong? Nancy seems broken to me, specifically the Response class...

Was it helpful?

Solution 2

Currently it returns HttpStatusCode.Unauthorized or a 401 which seems to be correct. I tried setting the ContentType to application/json as well and that didn't help.

When I changed it to return a 403 it sends back a 403. Although I suppose technically this isn't the correct response, it is better then the mysterious 303 I was getting before.

OTHER TIPS

I had the same problem as you - Nothing is broken.

FormsAuthentication.Enable(pipelines, formsAuthConfiguration);

This code adds functions to the before and after pipelines. It takes every 401 and and changes it to a 303, since you've defined that the user should be redirected if he's not logged in.

In order to prevent that from happening, you can set the DisableRedirect property to true. And you can actually do this automatically on all Ajax Requests like this:

new FormsAuthenticationConfiguration()
{
    ...,
    DisableRedirect = context.Request.IsAjaxRequest()
};

Also, make sure your request is setting the X-Requested-With header to XMLHttpRequest otherwise nanacy can't detect it's an ajax request. You can of course feel free to detect the proper requests differently (based on url, ...) in order to set DisableRedirect to true.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top