Access-control-allow-origin with multiple domains Access-control-allow-origin with multiple domains asp.net asp.net

Access-control-allow-origin with multiple domains


For IIS 7.5+ and Rewrite 2.0 you can use:

<system.webServer>   <httpProtocol>     <customHeaders>         <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />         <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" />     </customHeaders>   </httpProtocol>        <rewrite>                        <outboundRules>                <clear />                                <rule name="AddCrossDomainHeader">                    <match serverVariable="RESPONSE_Access_Control_Allow_Origin" pattern=".*" />                    <conditions logicalGrouping="MatchAll" trackAllCaptures="true">                        <add input="{HTTP_ORIGIN}" pattern="(http(s)?://((.+\.)?domain1\.com|(.+\.)?domain2\.com|(.+\.)?domain3\.com))" />                    </conditions>                    <action type="Rewrite" value="{C:0}" />                </rule>                       </outboundRules>        </rewrite> </system.webServer>

Explaining the server variable RESPONSE_Access_Control_Allow_Origin portion:
In Rewrite you can use any string after RESPONSE_ and it will create the Response Header using the rest of the word as the header name (in this case Access-Control-Allow-Origin). Rewrite uses underscores "_" instead of dashes "-" (rewrite converts them to dashes)

Explaining the server variable HTTP_ORIGIN :
Similarly, in Rewrite you can grab any Request Header using HTTP_ as the prefix. Same rules with the dashes (use underscores "_" instead of dashes "-").


There can only be one Access-Control-Allow-Origin response header, and that header can only have one origin value. Therefore, in order to get this to work, you need to have some code that:

  1. Grabs the Origin request header.
  2. Checks if the origin value is one of the whitelisted values.
  3. If it is valid, sets the Access-Control-Allow-Origin header with that value.

I don't think there's any way to do this solely through the web.config.

if (ValidateRequest()) {    Response.Headers.Remove("Access-Control-Allow-Origin");    Response.AddHeader("Access-Control-Allow-Origin", Request.UrlReferrer.GetLeftPart(UriPartial.Authority));    Response.Headers.Remove("Access-Control-Allow-Credentials");    Response.AddHeader("Access-Control-Allow-Credentials", "true");    Response.Headers.Remove("Access-Control-Allow-Methods");    Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");}


In Web.API this attribute can be added using Microsoft.AspNet.WebApi.Cors as detailed at http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

In MVC you could create a filter attribute to do this work for you:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,                AllowMultiple = true, Inherited = true)]public class EnableCorsAttribute : FilterAttribute, IActionFilter {    private const string IncomingOriginHeader = "Origin";    private const string OutgoingOriginHeader = "Access-Control-Allow-Origin";    private const string OutgoingMethodsHeader = "Access-Control-Allow-Methods";    private const string OutgoingAgeHeader = "Access-Control-Max-Age";    public void OnActionExecuted(ActionExecutedContext filterContext) {        // Do nothing    }    public void OnActionExecuting(ActionExecutingContext filterContext)    {        var isLocal = filterContext.HttpContext.Request.IsLocal;        var originHeader =              filterContext.HttpContext.Request.Headers.Get(IncomingOriginHeader);        var response = filterContext.HttpContext.Response;        if (!String.IsNullOrWhiteSpace(originHeader) &&            (isLocal || IsAllowedOrigin(originHeader))) {            response.AddHeader(OutgoingOriginHeader, originHeader);            response.AddHeader(OutgoingMethodsHeader, "GET,POST,OPTIONS");            response.AddHeader(OutgoingAgeHeader, "3600");        }    }    protected bool IsAllowedOrigin(string origin) {        // ** replace with your own logic to check the origin header        return true;    }}

Then either enable it for specific actions / controllers:

[EnableCors]public class SecurityController : Controller {    // *snip*    [EnableCors]    public ActionResult SignIn(Guid key, string email, string password) {

Or add it for all controllers in Global.asax.cs

protected void Application_Start() {    // *Snip* any existing code    // Register global filter    GlobalFilters.Filters.Add(new EnableCorsAttribute());    RegisterGlobalFilters(GlobalFilters.Filters);    // *snip* existing code}