Question

I'm trying to create area-specific behavior for the X-Frame-Options header in my application.

I have a single MVC 5 project with the following structure:

  • Several WebApiControllers in the "Root" of the MVC structure
  • Two "Areas" - one for my main site (called "App") and one for a bookmarklet (called "Bookmarklet")

"App" is the main area of my application. "Bookmarklet" causes a page to appear in an iFrame whenever a user clicks the bookmarklet (regardless of what site they are on).

I want the API and "App" area to be protected by the X-Frame-Options header, but the Bookmarklet MUST NOT have this header since its very purpose is to be displayed inside of an iframe from any website (the user clicks the bookmarklet, which opens the iframe and pre-populates a form to save the title and URL of the current page - think of it as a "Add to Favorites" feature that save your favorite links in the application).

I'm currently using the following inside my Global.asax:

    protected void Application_Start()
    {
        ...

        AntiForgeryConfig.SuppressXFrameOptionsHeader = true;                       
    }

Unfortunately, this suppresses the X-Frame-Options header across all areas. Is there a way to apply this behavior specifically to the Bookmarklet area and not the root or other Area of the application?

Note that I am aware of the clickjacking security risk associated with opening up X-Frame-Options. I am trying to mitigate this risk by placing login functions within the "App" area of the site (which I'd like to protect with X-Frame-Options). The "Bookmarklet" functionality (which cannot be protected by X-Frame-Options since it can be opened from any site that a user is visiting) therefore only contains limited data entry.

Was it helpful?

Solution

You can write a custom attribute to handle this scenario:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class SuppressHeadersAttribute : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        //suppress headers here
        //filterContext has access to the HttpContext
    }
}

Then have the controllers that you need to follow this patter inherit from a base controller that has this attribute.

 [SuppressHeader]
 public class BaseController : Controller
 {
 }

 public class YourController : BaseController
 {
     //Do Stuff
 }

Using this you can suppress the headers on only the things that need it.

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