Safari Ajax cors request not following redirect

2019-01-28 01:11发布

问题:

Basically, I have a login form that once authenticated it starts an Oauth2 process. Which works flawlessly until it has to do the final redirect which gets the access tokens. The login flow is as follows POST to /user/login redirects to /user/oauth/auth then redirects to the Oauth redirect_uri /user/oauth/redirect. The redirect_uri never happens and the request never hits the server.

If I hit that redirect using an Ajax request the cors works fine and I get the expected response it only seems to happen if I redirect twice.

The server shows these responses

[I 130226 10:16:38 web:1462] 302 POST /user/login (192.168.1.5) 156.01ms  (Session cookies set fine)
[I 130226 10:16:38 web:1462] 200 OPTIONS /user/oauth/auth?scope=&client_id=DemoApp&response_type=code&redirect_uri=http://192.168.1.5:8443/user/oauth/redirect/code (192.168.1.5) 1.86ms
302 GET /user/oauth/auth?scope=&client_id=DemoApp&response_type=code&redirect_uri=http://192.168.1.5:8443/user/oauth/redirect/code (192.168.1.5) 8.58ms

The last URL never get's hit. In Chrome, IE, FF the flow is the same except the server sees the request

[I 130226 10:16:38 web:1462] 302 POST /user/login (192.168.1.5) 156.01ms  
[I 130226 10:16:38 web:1462] 200 OPTIONS /user/oauth/auth?scope=&client_id=DemoApp&response_type=code&redirect_uri=http://192.168.1.5:8443/user/oauth/redirect/code (192.168.1.5) 1.86ms
302 GET /user/oauth/auth?scope=&client_id=DemoApp&response_type=code&redirect_uri=http://192.168.1.5:8443/user/oauth/redirect/code (192.168.1.5) 8.58ms
[I 130226 10:27:12 web:1462] 200 GET /user/oauth/redirect/code?code=57497058fbbf6003310ea22d3902ac67 (192.168.1.5) 0.54ms

In the Web Inspector I see the request but dies like a

I'm using Jquery 1.9 and here is the ajax request (granted I've got every option under the sun in here to try and make it work.)

$.ajax({
    type: "POST",
    url: reqUrl,
    data: data,
    dataType: "json",
    success: function(data, textStatus) {
            console.log(data);
            alert('logged in');

    },
    error: function(e){
        console.log(e);
    },
    complete: function(request, status) {
        console.log("headers=" + request.getAllResponseHeaders());
    },
    statusCode: {
    200: function(data) {
        console.log('yup we got it.')
    }
  },
  xhrFields: {
    withCredentials: true
  },
  crossDomain: true,
  async:true
});

JSONP is not an option as the initial post is sent over https and has to be a POST request. Again all other browsers including IE are working just fine, it fires the success response.

Safari fires the Statuscode 0 and error which is classic Origin policy errors but that redirect uri works in a standard ajax request bypassing the login. I doubt it's a access-control issue because the call would work if Safari would just fire it.

I'm pretty sure it has something to do with the request headers on the redirect and Safari is stopping the request. On the first successful 302 they look like this

Access-Control-Request-Method: GET
Origin: http://192.168.1.5:9090
Access-Control-Request-Headers: origin, accept-encoding, accept-language

But on the redirect uri they look like this (which makes sense as to why it's failing cause there are no access-control headers being sent but why??)

Origin: http://192.168.1.5:9090
Accept-Encoding: gzip, deflate
Accept-Language: en-us
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17
Accept: */*
Referer: http://192.168.1.5:9090/login

回答1:

Well it looks like this is a Safari thing, it will only follow the first redirect. Apple claims that this is the way the HTML spec is written. So.... Had to rework my flow to not redirect on /user/login and start the oauth process right away.