Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebAPI - Enable CORS for Subdomains

I would like to be enable CORS for a web-api application with the following criteria:

  1. Allow HTTPS or HTTP for the same site
  2. Ignore the SUBDOMAIN - Meaning mysite.com and www.mysite.com are same

I would like to do this for multiple sites in an elegant way, rather than putting all the permutations as comma delimited.

Thanks in advance!

like image 664
Mr. B Avatar asked Mar 30 '16 11:03

Mr. B


3 Answers

Here you go.

Adding Git gist if it requires any revisions or bug fixes.

public class WildcardOriginCorsPolicy : Attribute, ICorsPolicyProvider
    {
        private readonly string _origins;
        private readonly string _headers;
        private readonly string _methods;

        //private readonly CorsPolicy _policy;
        //
        // Summary:
        //     Initializes a new instance of the WildcardOriginCorsPolicy class.
        //
        // Parameters:
        //   origins:
        //     Comma-separated list of origins that are allowed to access the resource. Use
        //     "*" to allow all.
        //     "*.example.com" for subdomains
        //
        //   headers:
        //     Comma-separated list of headers that are supported by the resource. Use "*" to
        //     allow all. Use null or empty string to allow none.
        //
        //   methods:
        //     Comma-separated list of methods that are supported by the resource. Use "*" to
        //     allow all. Use null or empty string to allow none.
        public WildcardOriginCorsPolicy(string origins, string headers, string methods)
        {
            this._origins = origins;
            this._headers = headers;
            this._methods = methods;
        }

        public bool SupportsCredentials { get; set; }

        public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var policy = CreatePolicy(request.GetCorsRequestContext(), this._origins, this._headers, this._methods);
            policy.SupportsCredentials = this.SupportsCredentials;

            return Task.FromResult(policy);
        }

        private static CorsPolicy CreatePolicy(CorsRequestContext requestContext, string origins, string headers, string methods)
        {

            var corsPolicy = new CorsPolicy();
            if (origins == "*")
            {
                corsPolicy.AllowAnyOrigin = true;
            }
            else
            {
                var originsStringArray = origins.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                var requestOrigin = requestContext.Origin.ToLowerInvariant();

                foreach (var originItem in originsStringArray)
                {
                    ////Check if the current request uri matches with any of the wildcard origins.
                    if (Regex.IsMatch(requestOrigin, WildCardToRegularExpression(originItem)))
                    {
                        corsPolicy.Origins.Add(requestOrigin);
                    }
                }
            }

            if (!String.IsNullOrEmpty(headers))
            {
                if (headers == "*")
                {
                    corsPolicy.AllowAnyHeader = true;
                }
                else
                {
                    var headersStringArray = headers.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    corsPolicy.Headers.AddAll(headersStringArray);
                }
            }

            if (!String.IsNullOrEmpty(methods))
            {
                if (methods == "*")
                {
                    corsPolicy.AllowAnyMethod = true;
                }
                else
                {
                    var methodsStringArray = methods.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    corsPolicy.Methods.AddAll(methodsStringArray);
                }
            }

            return corsPolicy;
        }

        private static string WildCardToRegularExpression(String value)
        {
            return "^" + Regex.Escape(value).Replace("\\?", ".").Replace("\\*", ".*") + "$";
        }
    }

Use it like this.

var cors = new WildcardOriginCorsPolicy("*.example.com,http://localhost:*", "*", "POST,PUT,DELETE,GET,OPTIONS") { SupportsCredentials = true };
config.EnableCors(cors);
like image 169
Ahuman Avatar answered Oct 18 '22 21:10

Ahuman


The only way i can think of doing this besides explicitly specifying all the permutations is by implementing a custom CORS policy.

You can read more about it here.

like image 24
Fábio Junqueira Avatar answered Oct 18 '22 21:10

Fábio Junqueira


you can implement this dynamic for *.mydomain.com without the wildcard. You can refer the following method (Custom CORS Policy Providers)

public class MyCorsPolicy : Attribute, ICorsPolicyProvider
    {
        public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var policy = new CorsPolicy();
            var requestUri = request.RequestUri;
            var authority = requestUri.Authority.ToLowerInvariant();
            if (authority.EndsWith(".mydomain.com") || authority == "mydomain.com")
            {
                // returns a url with scheme, host and port(if different than 80/443) without any path or querystring
                var origin = requestUri.GetComponents(System.UriComponents.SchemeAndServer, System.UriFormat.SafeUnescaped);
                policy.Origins.Add(origin);
            }

            return Task.FromResult(policy);
        }
    }


    [MyCorsPolicy]
    public class TestController : ApiController
    {
    }

As already mentioned in other posts you can visit the url https://msdn.microsoft.com/en-us/magazine/dn532203.aspx for more info regarding Custom CORS Policy Providers

like image 40
vibs2006 Avatar answered Oct 18 '22 20:10

vibs2006