There is a well-known bug in Flash that causes it to completely ignore the browser’s session state when it makes a request. Instead, it either pulls cookies from Internet Explorer or just starts a new session with no cookies. GOOD CALL, ADOBE. And when I say this bug is well-known, I mean it was reported in Flash 8. It’s still sitting in the Adobe bug tracker. It has been triaged, it seems to have high priority, yet it remains unfixed. Again, GREAT job, Adobe.
Anyway, why should you care? Well, if you want to use Flash for anything, even something simple like AJAX file uploads with Uploadify, you better hope you don’t need authorization and authentication. But really, why would you want to authenticate users before letting them upload stuff to your site, anyway? There’s no possible way that could ever be exploited, right?
If you do decide that security is important (HINT: IT IS), there are some well-known hacks to work around it. None of them fit well with ASP.NET MVC though. Just when all seemed lost, I found this post from Ariel Popovsky that saved the day. I have wrapped his solution up in an easy-to-apply custom AuthorizationAttribute that you can tag to a controller or action method. Here’s the code:
/// <summary> /// A custom version of the <see cref="AuthorizeAttribute"/> that supports working /// around a cookie/session bug in Flash. /// </summary> /// <remarks> /// Details of the bug and workaround can be found on this blog: /// http://geekswithblogs.net/apopovsky/archive/2009/05/06/working-around-flash-cookie-bug-in-asp.net-mvc.aspx /// </remarks> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class FlashCompatibleAuthorizeAttribute : AuthorizeAttribute { /// <summary> /// The key to the authentication token that should be submitted somewhere in the request. /// </summary> private const string TOKEN_KEY = "AuthenticationToken"; /// <summary> /// This changes the behavior of AuthorizeCore so that it will only authorize /// users if a valid token is submitted with the request. /// </summary> /// <param name="httpContext"></param> /// <returns></returns> protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext) { string token = httpContext.Request.Params[TOKEN_KEY]; if (token != null) { FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(token); if (ticket != null) { FormsIdentity identity = new FormsIdentity(ticket); string[] roles = System.Web.Security.Roles.GetRolesForUser(identity.Name); GenericPrincipal principal = new GenericPrincipal(identity, roles); httpContext.User = principal; } } return base.AuthorizeCore(httpContext); } }
The filter checks the request to see if the authentication ticket was submitted. If so, it tries to decrypt it, then recreates the IPrincipal that is needed by the base AuthorizationAttribute to do its work. Just apply it to your controller, make sure Flash is submitted the value of the Forms Authentication cookie, and BAM, everything works.
Thank you!
Thank you!
Thank you!
I’v been banging my head against the wall wondering why Uploadify was not working with Authorize.