0

We have an ASP.NET MVC4 web application and in our QA environment we set up different "sites" as WebApplications on the same website, e.g.

www.mysite.co.uk/WebApp1
www.mysite.co.uk/WebApp2
www.mysite.co.uk/WebApp3

For all our cookies, we ensure that the cookie key contains an ID that ties that cookie to the specific Web Application, so there's no cross contamination.

Now this all works perfectly well the vast majority of the time. However, very occasionally in our DEV environment, we find that the GUEST shopper (not authenticated) can access a controller's Action method that is marked with the [Authorize] attribute.

My guess here is that the browser has been used with multiple TABS, each one pointing to a different Web Application, and occasionally the browser/server is getting confused over which ASPXAUTH cookie to use, and is using one from a different Web Application for a shopper who has authenticated. As I said, that's only a guess, but by debugging the site we're definitely hitting a break-point in the code that's supposedly protected with this Attribute.

It's not clear at this point how I may prevent this behaviour.

Thanks

Griff

Kartikeya Khosla
  • 18,743
  • 8
  • 43
  • 69
DrGriff
  • 4,394
  • 9
  • 43
  • 92
  • `For all our cookies, we ensure that the cookie key contains an ID that ties that cookie to the specific Web Application, so there's no cross contamination.` - can you expand on exactly how this works in your question? If this is working correctly then it shouldn't have authorised on the wrong site. – SilverlightFox Jul 24 '14 at 13:08
  • That refers to the cookies we manage in our application. The ASPXAUTH cookie is outside of our control (I believe), so I don't know whether it's tied to an application or just the site. If the site, then is it possible to tie it to an Application? – DrGriff Jul 24 '14 at 15:08
  • You can either add the ID to the encrypted token that gets stored inside `ASPXAUTH` and check this per request, or you could encrypt the token with a different key per site. You should also have a custom name for this cookie so they can co-exist within your DEV environment. – SilverlightFox Jul 24 '14 at 15:11
  • Any links as how to change the ASPXAUTH cookie's behaviour? I would have thought that this cookie is locked-down by the ASP.NET framework and thus it's name and behaviour would be difficult to change. – DrGriff Jul 24 '14 at 17:20
  • And in addition, how would we get to read this cookie? It's used the the ASP.NET framework and determines whether the user is Authorized before letting them run the code in the controller's method. If we receive multiple ASPXAUTH cookies, how would we instruct the ASP.NET framework to use one rather than the other? Is this something that we can do in (say) a module (which gets fired before the controller is called)? – DrGriff Jul 24 '14 at 17:28

1 Answers1

0

For all our cookies, we ensure that the cookie key contains an ID that ties that cookie to the specific Web Application, so there's no cross contamination

You are storing the ID within custom cookies, but it appears you are not storing this within the auth cookie that ASP.NET uses to grant access to code marked with the [Authorize] attribute.

You can either add the ID to the encrypted token that gets stored inside the auth cookie and check this per request, or you could encrypt the token with a different key per site.

Fortunately the FormsAuthenticationTicket constructor includes a userdata parameter that can be used for custom data.

 public FormsAuthenticationTicket(
    int version,
    string name,
    DateTime issueDate,
    DateTime expiration,
    bool isPersistent,
    string userData
)

You can follow this guide in order to easily store multiple pieces of information using the JSON format like so:-

public static class HttpResponseBaseExtensions
{
    public static int SetAuthCookie<T>(this HttpResponseBase responseBase, string name, bool rememberMe, T userData)
    {
        /// In order to pickup the settings from config, we create a default cookie and use its values to create a 
        /// new one.
        var cookie = FormsAuthentication.GetAuthCookie(name, rememberMe);
        var ticket = FormsAuthentication.Decrypt(cookie.Value);

        var newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration,
            ticket.IsPersistent, userData.ToJson(), ticket.CookiePath);
        var encTicket = FormsAuthentication.Encrypt(newTicket);

        /// Use existing cookie. Could create new one but would have to copy settings over...
        cookie.Value = encTicket;

        responseBase.Cookies.Add(cookie);

        return encTicket.Length;
    }
}

You should also have a custom name for this cookie per site so they can co-exist within your DEV environment.

SilverlightFox
  • 32,436
  • 11
  • 76
  • 145
  • Excellent, that seems clear on how to add the custom data to the ASPXAUTH cookie - thanks. So, what about the incoming Request? My guess here is that I would have to override the default [Authorize] attribute with our own and in that check that this ASPXAUTH cookie contains that custom information I set. But, what if it doesn't? What if it's one from a different Web Application on my site? How would I pick the correct one? – DrGriff Jul 25 '14 at 06:53
  • @DrGriff: [This answer](http://stackoverflow.com/a/18139294/413180) may be useful - you can check the value on every request before it is processed by your page at all and expire the ticket if it is the wrong ID for the site. This should never be the case though if you set different cookie names per site for the auth cookie ([Simply set the `name` attribute in the `forms` element of `web.config`](http://msdn.microsoft.com/en-us/library/1d3t3c61(v=vs.85).aspx)). However you should definitely check this to secure your applications. – SilverlightFox Jul 25 '14 at 08:16
  • @DrGriff: Need any further help? – SilverlightFox Jul 29 '14 at 10:09