2

I have three domains but the same code base (Domain X, Domain Y, Domain Z) and Accounts website A

If a user tries to sign in accounts from domain X, I wanted to SSO in the other two domains (Browser Scenario: third party cookies blocked).

I tried the following approach,

  1. Go to Accounts from Domain X
  2. Sign In
  3. Get the required authentication token info and posts an XHR request to Domain Y to create a cookie.

When I check the request in Network, the required cookie is set in the response cookies, but when I open Domain Y separately the cookie is not present in the Application Cookies.

Can anyone please tell why the created cookie via XHR request is not accessible by the main domain? Kindly help.

XHR request (withCredentials set to true):

$.ajax({
    type: "POST",
    data: result,
    url: result.uri,
    beforeSend: function (xhr) {
        xhr.withCredentials = true;
    },
    success: function (data) {
        console.log(data);
    }
});   

Cookie Info:

HttpOnly: true Secure: false SameSite: None

enter image description here

Kannan M
  • 121
  • 1
  • 3

3 Answers3

2

You can simplify the work with cookies by using following approach:

  • After successful authentication at host A this host generates a token, redirects the request to the host B and includes the token in the URL, like https://domain-b.com/authenticate/4874fdcf-3b6b-4793-a1c5-018d2648cf48
  • Browser sends this request to the host B
  • The host B receives this request and asks host A about the details regarding this token: What user name is associated with it, from when till when is it valid etc.
  • After host B received needed details and hey are valid, it considers it as successful authentication and, if needed, sets its own cookie for ts domain. From now on the host A is not involved any more.
mentallurg
  • 8,536
  • 4
  • 26
  • 41
  • This is a viable solution with the compromise of host B needing to do an extra request to Host A in order to obtain the full details of the person who logged in. – Kevin Johnson Sep 02 '21 at 18:55
  • @KevinJohnson: Compromise? Compromise between what and what? The OP says that one server provides authentication, the other wants to reuse the authentication from the first one, for SSO. So there will always be at least 2 requests. And my approach contains also 2 requests. What compromise do you mean? – mentallurg Sep 03 '21 at 22:46
  • The total amount of requests may be the same but the user experience will be different. OP's intended way is to set the cookie for the other domains while the user is still using domain X(which I understood from: "I have three domains but the same code base") in preparation for the potential future event of this user navigating to domain Y or Z. In your case, after navigating to domain Y or Z, the user has to wait an additional request for the token exchange to happen and obtain the required cookie(s). – Kevin Johnson Sep 04 '21 at 12:04
0

From the documentation at MDN:

Note: XMLHttpRequest responses from a different domain cannot set cookie values for their own domain unless withCredentials is set to true before making the request, regardless of Access-Control- header values.

It is unknown if your request already includes withCredentials since you don't show any code in your question.

Also make sure that the cookie has the correct SameSite attribute set since browsers started change the default to Lax which might not be what you need in your use case.

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
  • Thanks for your reply. yes I included withCredentials as true in XHR and samesite set as 'none'. Not sure if I'm missing something. – Kannan M Oct 19 '20 at 15:38
  • Got it working, but if third party cookie settings is blocked, the set cookie doesn't work – Kannan M Oct 19 '20 at 17:27
0

I assume the parenthetical about third-party cookies being blocked was edited in later? Because that's the obvious source of the problem. You're trying to set a third-party cookie (it's not like the browser has any way to tell you own all three sites) and of course that's blocked unless third-party cookies are allowed. They're a privacy risk, so all browsers allow blocking them and many do it by default.

As for how to solve this: there are a few decent ways I can think of.

  • Just load a page (perhaps /crossDomainAuth or similar) from each site, probably in a small iframe. You'd need to pass some authentication token in each request, ideally in a POST body but URL parameters would work too if they're short-lived and single-use. Each site would, upon verifying the token, create and persist its own session token (for its own domain) in the browser.
  • For each site, when a user visits and doesn't have an active session, attempt a with-credentials CORS request to the other sites. If the user is logged into any of them, the logged-in site returns a token that can be used to create a session for the site the user is currently visiting. That way, if the user is logged into any of the sites, they can automatically also be logged into any other site when they visit it.
  • Both of the above approaches are fine for three sites, but scale poorly to huge numbers (such as StackExchange has). Another option is to designate one of the domains (an existing or a new one) as the canonical authentication domain for your sites. Authentication is either performed via this domain, or you immediately do something like the first suggestion with this domain when you log into one of the others. Whenever a seemingly-unauthenticated user visits any domain except the authentication domain, a with-credentials CORS request is made to the canonical authentication domain to see if the user has any active session on any of the sites. This is sort of a hybrid of the previous options, so it's a bit more work to set up, but it scales as far as you want.
CBHacking
  • 40,303
  • 3
  • 74
  • 98