Safari not prompting for credentials

Hi there,


a few days ago we changed our application/server structure leading to problems with our authentication. What we’re basically doing is SSO using NTLM, by calling a authentication server from client side, returning an authentication token.


So if you open a application hosted on domain A the client requests a token from domain B (cors). In case of iOS or MacOs this normally leads to a login prompt as part of the challenge/response handing, but – since we moved to different domains - nothing is showing up and the user is getting a 401.


I debugged the problem and stripped it down to a more simpler case by just using a basic html page (domain A) making a xhr request to domain B, that contains a simple auth service which requires basic authentication and therefore also wants some credentials that would be entered in a login prompt – leading to the same behavior.


What I’ve read and done so far:

  • Both servers (domain A and B) communicate over https
  • A wildcard certificate is used – but if you call domain B directly (without cors) the login prompt is showing up
  • withCredentials is set on xhr request
  • The auth server responds with
    • Access-Control-Allow-Credentials: true
    • Access-Control-Allow-Origin: https://domainB.mycompany.com (so no wildcard)
    • Access-Control-Allow-Headers: * (I also tried combinations with "Authorization" and "Origin")
    • Access-Control-Allow-Methods: * (I also tried allowing OPTIONS and GET directly)


Tested platform/browser combinations:

  • Windows: IE, Chrome, FF – all working
  • Android: Chrome, Samsung Browser - all working
  • MacOS: Chrome (working), Safari (not)
  • iOS: Chrome, Safari – both not working (debugging showed same console output as Mac)


Unfortunately, i don't know what to test or search anymore and hope someone could help me.


Please let me know if you need any more information.


Thanks! Denis

Replies

So in the meantime i replaced the authentication server by a simple jsp that's setting the response headers, just to be sure that there is no kind of magic leading to the problem


response.setHeader("Access-Control-Allow-Origin","https://serverA.company.com" );
response.setHeader("Access-Control-Allow-Credentials", "true");
   
response.setHeader("Access-Control-Allow-Headers", "...");
response.setHeader("Access-Control-Expose-Headers", "...");
   
response.setHeader("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE" );
response.setHeader("Access-Control-Max-Age", "86400");
   
response.setHeader("Content-Type", "text/plain; charset=UTF-8");
   
if("OPTIONS".equals(request.getMethod())) {
   response.setStatus(200);
} else {
   response.setHeader("WWW-Authenticate", "Basic realm=\"Realm\"");
   response.setStatus(401);
}


As headers i specified the standard and non-standard request fields you can find on wiki.. way too much, but rather too much than too little 🙂 Also exposing everything and other options aren't necessary, but i tried to get it in a working state and reduce the option from there on


The calling side is quite as simple


var request = new XMLHttpRequest();
request.withCredentials = true;
request.open("GET","https://serverB.company.com/auth/index.jsp");
request.send(); 


I switched the wildcard certificates to multi-domain ones including the two domains and rolled it out on both servers.


Result: Working in all browsers except Safari (or Chrome on iOS)...


Does anyone have a clue what might be wrong here or what's missing?