views:

500

answers:

3

Hello,

I am using successfully custom authorization in ASP.NET MVC. It simply involves a comparison between User.Identity and the owner of the object in context.

It works like a charm when used in simple conditions. It becomes more complicated when I try to call 2 actions in one web request.

Lets say I want to display an image which would be generated on-the-fly by my application. This image is generated by a controller, thus, it can be referenced by an URL even if it doesn't exist physically. I have decided that the user must be signed in and be the owner to view it, so I apply my authorization mechanizm to it.

Example: <img src="http://myapplication.com/images/generate/3" />

When I include such an image in a page via its action hyperlink, I expect that the authenticated user will still be in context on server side when the image is generating. This is not the case in my tests. The image never displays because my authorization check doesn't work. In the image controller, User.Identity is empty as if the user has not signed it.

In the meantime, the same user is still signed in to the website and can continue to browse with his identity in context... without those images working properly.

I wonder how to make this process work securely...

Thank you very much!

Marc Lacoursiere RooSoft Computing inc.

+1  A: 

Just wondering if you've checked if

Thread.CurrentPrincipal

is also empty in the controller? It should contain the same value.

Another suggestion would be to store the User.Identity value in a session?

Peter
Are you certain that the two requests will be made on the same thread?
RooSoft
I don't see why there would be two threads? First a request is made to render the page with your img tag inside it (not the actual bits of the image). Then, once the browser renders your img tag a request is made to your controller to get your image. There is in both cases only one thread active?
Peter
I wonder if we can rely on that fact because of the stateless nature of ASP.NET MVC in the first place...In theory, on a load balancing setup, the two requests could be made on two different servers, which implies two different threads.
RooSoft
A: 

You need to set up your identity in global.asax on every request. I'm using a custom Principal and Identity for this.

private void Application_AuthenticateRequest(object sender, EventArgs e)
{
    if (!Request.IsAuthenticated)
    {
        SetIdentity(new MyIdentity
                   { Type = UserType.Inactive, Id = int.MinValue });
    }
    else
    {
        HttpCookie authCookie = Request.Cookies[
            FormsAuthentication.FormsCookieName];
        if (authCookie != null)
        {
            FormsAuthenticationTicket authTicket =
                   FormsAuthentication.Decrypt(authCookie.Value);

            var identity = Repository.GetIdentity
                   (authTicket.Name, new HttpRequestWrapper(Request));
            SetIdentity(identity);
        }
    }
}

private void SetIdentity(MyIdentity identity)
{
    Context.User = new MyPrincipal { Identity = identity };
    Thread.CurrentPrincipal = Context.User;
}

This works, but I don't guarantee it to be secure. You should review this article on FormsAuthentication vulnerabilities prior to going live with this code. You have to understand that this code assumes the cookie is valid and hasn't been hijacked. There are some additional security measures that can be taken to reduce these vulnerabilities which this code doesn't show.

Will
+1  A: 

This may be when the site link in browser is http:\www.mysite.com (or http:\subdomain.mysite.com ) and you are using http:\mysite.com\image\5 in your application. Form authentication uses cookies. And these cookies may belong to domains and subdomains.
To find out what is going on I suggest to use FireFox with FireBug installed. Enable Net and Console tab for your site and make a complete refresh of the page. After you'll see requests in one of these tabs (Net tab exactly). At the left of the request you can see 'a plus' button, after you click it you'll see Headers and Response tabs (more detailed description of firebug). Have a look at Headers tab and try to find something like FORMAUTH (or what you've set in config as a forms cookie name). If you not see it - the problem is in domains.

zihotki