简体   繁体   中英

IE11 does not set x-cfrtoken HTTP header, unless with an InPrivate window, this causes server to respond with HTTP 403 Access Denied

I've been baffled by this for two days now. The situation:

  • Simple website, running in Websharper, login screen, single view, through XHR with application/json responses
  • The site is run from within an iframe with different domains (I cannot change that, but I have access to both sites). Without iframe there are no problems.
  • You should see an error with faulty login, but this doesn't work in IE11 on Windows 7. It works in the same IE11 in InPrivate mode and any IE11 on Windows 10 . It is not a caching issue.
  • The site sets cookies, but works cookieless if cookies cannot be set (ie, iPhone)

It appears that in InPrivate mode, the x-csfrtoken is set in the request header, outside InPrivate mode this header is not set . The server then returns an HTTP 403 error, which seems to be at the root of the problem.

I don't know how to instruct the server (IIS) to ignore this token.

To see this behavior in action, got to that site and type in anything, then click "Inloggen". You should see a login-error (in Dutch), but in IE11 on Windows 7, this error does not appear.

I tried this solution by Microsoft, on improper rights on LocalLow , but it did not resolve the issue and seems otherwise unrelated.

Apparently this is a bug in IE11 on Windows 7 and Windows 8 / 8.1. I found out that the browser does send the csrftoken cookie, but forgets the required x-csrftoken HTTP Header parameter, which all other browsers, including older and newer versions of IE and IE11 on Windows 10 properly send.

If your toolchain protects itself by validating the x-csrftoken (which is recommended by any framework), then this fails with IE11. It was discussed here for WebSharper , but without a complete solution yet.

The workaround that I found that worked properly is the following. It's hacky, it alters the HTTP headers upon arrival, but other tools do that too (think proxy servers for one). Here's code to place in the global.asax.fs in F# if you are using WebSharper (a bit messy, but I'll leave cleaning up as an exercise for the reader ;)).

member __.Application_BeginRequest(sender: obj, args: System.EventArgs) =
    HttpContext.Current
    |> function
    | null -> ()
    | ctx ->
        match ctx.Request with
        | null -> ()
        | req ->
            match req.Cookies.Item "csrftoken", req.Headers.Item "x-csrftoken" with
            | null, null -> ()
            | cookie, null ->
                // fix for IE11, which does not always set the HTTP Header "x-csrftoken"
                try req.Headers.Item "x-csrftoken" <- cookie.Value
                with _ -> ()       // ignore possible errors
            | null, _ ->
                // if header is set but cookie is not, there's nothing we can do (cookie collection is read-only)
                ()
            | cookie, csrfHeader when cookie.Value <> csrfHeader ->
                try req.Headers.Item "x-csrftoken" <- cookie.Value
                with _ -> ()       // ignore possible errors
            | _ ->
                ()      // all is fine, the default: cookie "csfrtoken" and header "x-csfrtoken" are equal

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM