Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multi-domain environments #662

Closed
aeneasr opened this issue Aug 24, 2020 · 25 comments
Closed

Support multi-domain environments #662

aeneasr opened this issue Aug 24, 2020 · 25 comments
Labels
feat New feature or request.
Milestone

Comments

@aeneasr
Copy link
Member

aeneasr commented Aug 24, 2020

Is your feature request related to a problem? Please describe.

It is currently not possible to set up ORY Kratos' Login Session Cookie in such a way that it is valid for multiple domains at once (e.g. foo.com, bar.com). The user will have to log in on both domains individually.

Describe the solution you'd like

There should be a way to get this working.

Additional context

This works as demonstrated for google.com and youtube.com where sessions are synchronized. They apparenlty use HTTP redirects to get it working with query parameters that include the session.

@aeneasr aeneasr added the feat New feature or request. label Aug 24, 2020
@aeneasr aeneasr added this to the unplanned milestone Aug 24, 2020
@Raou1d
Copy link

Raou1d commented Feb 3, 2021

So the end goal would be SSO? Isn’t Hydra the tool for that? I think Google and YouTube also use OIDC.

@aeneasr
Copy link
Member Author

aeneasr commented Feb 4, 2021

No they do not! Yes SSO is the end goal. Hydra is for federation

@dan2kx
Copy link

dan2kx commented Sep 17, 2021

Could this be achieved by sending a Set-Cookie header to the callback url, allowing the OAuth consumer to create a cookie for the origin domain?

@daattaa
Copy link

daattaa commented Nov 8, 2021

What is the complexity of this? Does it require an architecture change?

@aeneasr
Copy link
Member Author

aeneasr commented Nov 9, 2021

Yes this is quite complex! It would first require a design document that explains a secure flow for setting cookies across multiple domains. Probably looking at how google does it for youtube?

@Serhii-the-Dev
Copy link

@aeneasr Just a random crazy idea: is it worth to consider Trust Tokens as an alternative to a chain of redirects or it's too optimistic taking into account those are not wide-spread?

@aeneasr
Copy link
Member Author

aeneasr commented Nov 9, 2021

What are trust tokens? 😅

@aeneasr
Copy link
Member Author

aeneasr commented Nov 9, 2021

Ah you mean https://web.dev/trust-tokens/?

@Serhii-the-Dev
Copy link

Serhii-the-Dev commented Nov 13, 2021

@aeneasr yes, but nevermind, it was a stupid idea...I did a small research and AFAIK now the Trust Tokens are designated for identification and not authentication.

@mitar
Copy link
Contributor

mitar commented Dec 8, 2021

I think this will be very hard to pull off because many approaches to this are also used by ads industry for tracking users and browsers are actively trying to protect users. Safari is a prime example of this.

@r4j4h
Copy link

r4j4h commented Dec 21, 2021

I am probably repeating the additional context from the OP in so many more words, but wanted to share my thoughts incase they are useful.

I am vaguely familiar with an older strategy where foo.com redirects browser to a page on bar.com that sets the same cookie data just on its domain. The cookie data is passed in the sub-path or request parameters in some way:

  • If cookie material is safe enough, foo.com can send it via request parameter to a page on bar.com. That page validates the request parameter looks like normal cookie data's format, then returns instruction to browser to set cookie data to those request parameter's contents when responding with the bar.com page.

  • If cookie material isn't public, shared data store is an option. foo.com stores it under a key/id in a place where both foo.com and bar.com backends can reach, then foo.com transmits that key/id in request parameters like above. This time bar.com does some validation that the request parameter looks like a valid key/id, then looks up cookie data to set from shared store and return instruction to browser to set it.

  • If cookie material isn't public, and shared data store is not an option, server->server is an option. foo.com backend first makes a call to bar.com telling it an id to store cookie material under somewhere it can (short term in-memory works) and waits for bar.com to respond before foo.com then redirects browser to bar.com with that same id given out of band. Now bar.com validates that it looks like a valid key/id, then looks up cookie data to set from its store (which was pre-populated out of band) and returns instruction to browser to set it.

For setting on login or something for future use, consider bar.com cookie setting redirect could redirect back to foo.com when done.

Similarly, if there are more than 2 domains involved, bar.com page could continue the same pattern to baz..com which could continue the same pattern yet again to fum.com.

User experience is not that great, but it does work.

https://jisajournal.springeropen.com/articles/10.1186/1869-0238-4-13#Sec2 describes the first way in more detail:

Many variants of the same folk protocol exist where one or more Web sites use another site as a cookie manager (CM): to set a cookie the Web sites redirect the browser to the manager passing the necessary data as a request parameter; the manager sets the cookie when redirecting back to the requesting page. (At this point the browser associates the cookie with the cookie manager’s host or domain.) To receive a cookie, they do a redirect to the CM who receives the cookie from the browser and performs another redirect (back) passing the data, also as a request parameter. While this is a working solution, it requires multiple redirects (two per request) increasing communication overhead and design complexity. [...]

And then the third in more as well:

Callaghan et al. proposed a proxy-based solution that allows non-cooperating Web servers to communicate using standard HTTP cookies [16]. A forwarding proxy is configured to treat a group of Web sites as one; it captures cookies from passing HTTP traffic and makes them available to communicating browsers and servers by inserting Cookie and Set-Cookie HTTP headers as needed. In a more complex configuration, Callaghan et al. set up a “cookie manager” URL that the proxy itself responds to. Cross-site cookies are associated in the browser with that URL. When a browser sends a request to a participating server, the proxy initiates a cookie transfer from the “cookie manager” (CM) as follows:

  1. Redirect to the CM keeping the target URL as a request parameter.

  2. Intercept the request as the CM, receive all cookies, and redirect to the target URL encoding the cookies as request parameters.

  3. Intercept the request again, convert the request parameters into cookies using the Set-Cookie header, and redirect to the target URL again.

After this the cookies will be associated with the target host as well as the CM itself. The drawback of this solution (in addition to multiple redirects) is that it tightly couples components in the user’s domain (the forwarding proxy) and the application’s domain (the Web servers). Such coupling may be achieved and maintained in a controlled environment, for example, within an enterprise, but cannot be easily replicated in other settings. Callaghan et al.’s approach was driven by constraints imposed by the same origin policy. [...]

@aeneasr
Copy link
Member Author

aeneasr commented Jan 2, 2022

Thank you! This is indeed very helpful!

A major challenge with this model is that we need to ensure that the cookie is bound to the same client. A simple example may be as follows:

  1. Eve (evil) signs in to foo.com and receives the redirect to bar.com but does not execute it (because of potential token replay defense)
  2. Eve (evil) sends link bar.com?cookie=abcd to Alice (good)
  3. Alice (good) clicks link or executes it (e.g. email with an image)
  4. Alice is now signed in as Eve even though she is not Eve

Depending on your threat model this might sound like not a problem (why would eve try to sign in alice). However, it is an attack surface in certain scenarios that needs to be considered.

In order to ensure this methodology is secure, we need to follow some of OAuth2's playbook:

  1. Ensure replay is not possible
  2. Ensure intended audience matches
  3. Ensure TTL is short and long enough

Maybe it would even make sense to embed a kind-of-hidden (aka no user interaction required) OAuth2 dance to support this use case?

@sebmellen
Copy link

We were thinking about building our own "hidden OAuth2 dance"... We've come to the conclusion that we don't know enough about security to do so safely. However if Ory builds this into Kratos natively, we would use it.

What do you think of the approach of using Kratos for our main domain, and then using Hydra to delegate OAuth2 access for other "whitelabeled" domains running the same product? This would come with overhead on building our API implementation (having to support both Hydra and Kratos auth flows, depending on the user's domain), but we believe it would be possible. Can you think of any security downside?

@dystopiandev
Copy link

It's incredible work you guys are doing here. Internally supported multi-domain cookies would save a lot of people from hacks that aim to achieve what google does in their dance.

I think I read somewhere that they use 0px images to invoke the other domains, ergo set the cookies. Never got to verify that piece of info though.
Keep up the good work.

@Rodolffo
Copy link

Rodolffo commented Aug 22, 2022

Hey @dystopiandev, I know this is an old issue, but just wanted to share this as it might be helpful for OP.

The 1px gif was as far as I remember was (or probably still is) used by Stack Exchange so they can log you into all of their domains, you can read more here: https://meta.stackexchange.com/a/309823. The problem with this is that most browsers don't allow 3rd-party cookies anymore (for privacy reasons), so Google achieves it differently.

If you log in anywhere to your Google account (e.g. I did it from the main page), you're sent to accounts.google.com where the login form is. Then - after successful authentication -, you're also sent to YouTube with a simple 302 redirect, like this:
image
The URL has a few request parameters, one of them seems to be a token so YouTube can check with the IdP (Google) if it can create a session for you. The redirect is required as the only way to set a cookie for a different domain is if the browser has a page on that domain open. Then you're redirected to the original page you initiated the login from, obviously you can't really see this (except in the network tab) as it happens very quickly.

So I think what OP asks can be implemented this way.

@aeneasr
Copy link
Member Author

aeneasr commented Oct 28, 2022

Just wanted to let you know that Ory Kratos now has a native integration with Ory Hydra (works out of the box on https://console.ory.sh) which basically allows multi-domain environments by using SSO with OpenID Connect.

This doesn't really solve the issue here. We will introduce multi-cname support in the cloud system which uses some wrappers to make it work with cloudflare.

In the end, I'm not sure if it really makes sense to support the use case Google has laid out. This works well with one or two sites, but does not scale to 10 or 15 sites as you would be stuck in redirects for a while as a user.

@aeneasr
Copy link
Member Author

aeneasr commented Nov 1, 2022

Having given this more thought we are convinced that for multi-domain and multi-brand environments, OIDC is the way to go to ensure smooth SSO. All other approaches are not really scalable due to e.g. number of redirects as well as other issues (cross-site logout for example). Therefore we’re closing this as resolved :)

@aeneasr aeneasr closed this as completed Nov 1, 2022
@davidspiess
Copy link

Just wanted to let you know that Ory Kratos now has a native integration with Ory Hydra (works out of the box on https://console.ory.sh) which basically allows multi-domain environments by using SSO with OpenID Connect.

Hey @aeneasr, congrats to the 2.0 hydra release!
Is there any documentation on how to configure hydra to use kratos as identity provider?

@lapnd
Copy link

lapnd commented Jun 20, 2023

Thanks

@rdp-studio
Copy link

Having given this more thought we are convinced that for multi-domain and multi-brand environments, OIDC is the way to go to ensure smooth SSO. All other approaches are not really scalable due to e.g. number of redirects as well as other issues (cross-site logout for example). Therefore we’re closing this as resolved :)

Can multi domain cookies be implemented? For example, if Kratos runs on both api.a.com and api.b.com, I would like to configure the cookie domain name as a.com when logging in through api.a.com, and b.com when logging in through api.b.com.

@Serhii-the-Dev
Copy link

Having given this more thought we are convinced that for multi-domain and multi-brand environments, OIDC is the way to go to ensure smooth SSO. All other approaches are not really scalable due to e.g. number of redirects as well as other issues (cross-site logout for example). Therefore we’re closing this as resolved :)

Can multi domain cookies be implemented? For example, if Kratos runs on both api.a.com and api.b.com, I would like to configure the cookie domain name as a.com when logging in through api.a.com, and b.com when logging in through api.b.com.

If you need to share accounts between those two domains, the easiest way IMHO would be to have 2 Kratos instances running for each domain separately pointed to a single database.

@rdp-studio
Copy link

Having given this more thought we are convinced that for multi-domain and multi-brand environments, OIDC is the way to go to ensure smooth SSO. All other approaches are not really scalable due to e.g. number of redirects as well as other issues (cross-site logout for example). Therefore we’re closing this as resolved :)

Can multi domain cookies be implemented? For example, if Kratos runs on both api.a.com and api.b.com, I would like to configure the cookie domain name as a.com when logging in through api.a.com, and b.com when logging in through api.b.com.

If you need to share accounts between those two domains, the easiest way IMHO would be to have 2 Kratos instances running for each domain separately pointed to a single database.

Thank you, I will give it a try. I also want to manually implement the initial idea of this issue, 302 redirect to configure cookies.

@Serhii-the-Dev
Copy link

Serhii-the-Dev commented Jul 12, 2023

@rdp-studio it doesn't seems to me you need a redirect, your case is covered in the Multi-domain cookies documentation. All you need to do is to configure Kratos instance hosted on api.a.com to set session cookie to a.com, and the same thing for the b.com accordingly.
I had a similar approach for a multi-tenant application, however in our environment all the cookies are set for api.tenant.com as Kratos seats behind a reverse proxy on the API domain, while a web server is hosted on tenant.com. We are also using Oathkeeper to authorize requests to the API basing on the session cookie mutating the credentials into JWTs which are consumed by those API services.

@rdp-studio
Copy link

rdp-studio commented Jul 12, 2023 via email

@mohamed--abdel-maksoud
Copy link

so I proposed in my previous message to set up cookies via redirect (and I've implemented it, It works well).

@rdp-studio this is neat, could you share your implementation? This solves a lot of pain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat New feature or request.
Projects
None yet
Development

No branches or pull requests