Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CORS Error on browser back button

I have a ASP.NET Web API 2 Service. And multiple client(angular) applications talks to that service. the applications and the service are published on different sub domains, like the following:

service.mydomain.com

app1.mydomain.com

app2.mydomain.com

I used Microsoft.AspNet.WebApi.Cors - NuGet package to enable CORS, it is working fine, except for one scenario: When the user opens one application (app1.mydomain.com). Then navigates to another (app2.mydomain.com). Then presses the browser back button. the follwoing CORS Error:

The 'Access-Control-Allow-Origin' header has a value 'http://app2.mydomain.com' that is not equal to the supplied origin. 
Origin 'http://app1.mydomain.com' is therefore not allowed access

I Configured The Microsoft.AspNet.WebApi.Cors - NuGet package, as follows:

public static void Register(HttpConfiguration config)
        {
        var cors = new EnableCorsAttribute(
                //to-do allow cross domains for all maarif.com sites
                origins: "*", //and also tried "http://app1.mydomain.com, http://app2.mydomain.com" gives same result
                headers: "*",
                methods: "*") {SupportsCredentials = true};

            config.EnableCors(cors);
        }

I traced the Origin header values on the server. I put the following code in the service 'global.asax' :

protected void Application_BeginRequest()
        {
            var origin = HttpContext.Current.Request.Headers["Origin"];

            if (origin != null )
            {
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", origin);
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "*");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "*");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
            }
        }

The problem happens when user clicks back button form 'app2.mydomain.com' to 'app1.mydomain.com', the origin sent with the request is 'app2.mydomain.com', and there that is what the service allows access to: HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", 'app2.mydomain.com');

Any Way around this?

Note that I can't put '*' because the requests are authenticated.

like image 387
yass Avatar asked Jan 01 '17 05:01

yass


1 Answers

The problem is due to the cache mechanism of browser. Because the browser would use the data from cache, even for AJAX request, when you clicked the BACK button.

For this, the browser wouldn't resend the CORS preflight to check the Access-Control-Allow-Origin for the origin of previous page. Then it would use the latest Access-Control-Allow-Origin, which is the app2.mydomain.com, so that the app1.mydomain.com should fail.

A simple solution is adding a timestamp or a random string at the end of the api querystring, for example:

js:

let url = 'https://service.mydomain.com/xxxxx?v=' + Date.now();

However it would ignore Access-Control-Max-Age, which makes a CORS preflight every request to the service.mydomain.com.

Or you can force opening all links to other origin in a new window, so that there is no BACK actions could be done.

Except these, I can not find any other solutions.

Updated:

I tested later after this anwser, and then found the final solution:

Add following HTTP response headers in the service.mydomain.com, and then all is ok.

http:

Cache-Control: no-store,no-cache,must-revalidate
Pragma: no-cache

Just disable all cache of the AJAX requests. And the CORS Max-age works too.

Now it works in Chrome and Firefox. I didn't try other browsers, but I think it should be nothing different.

like image 118
Angus Fenying Avatar answered Oct 01 '22 16:10

Angus Fenying