Best practise to support subdomain-based multi-tenancy


#1

Hi,

We’re running a multi-tenant web app, where each tenant accesses their environment via their own subdomain, similar to how Slack does that, like my-company.our-webapp.com for example

Technically each subdomain is a dedicated application server connected to a dedicated database per tenant. The database stores all the users and they authenticate (login) directly on that dedicated application server.

The rest api is exposed (www.)our-webapp.com/api/vx.x.x/tenant_id/yyyyy/…, where there our api backend knows which backend database to connect to, based on the yyyyy for the tenant_id in the api url.

My question is this: what would be the best practise in such a setup for Hydra?

I’ve read somewhere that it is not advised to have a single Hydra instance for all tenants, so then it would be a Hydra instance per tenant? Is this realy the best practise, cause I feel that being quite a bit overhead.

On the other hand, if we’d just have a single Hydra instance, could we make it work properly, in a sense that the url for the consent app would likely have to be something like my-company.our-webapp.com/consent?.…, where the subdomain part (‘my-company’) would have to somehow be dynamic

I’m a bit at a loss trying to wrap my head around all the parts involved in a Hydra integration in a scenario as described above and whether it’s doable at all.

I did read up on the upcoming changes to the consent flow in https://github.com/ory/hydra/issues/772, but not sure whether those changes would help my case, make it harder or make no difference at all

Hoping someone can shed some light on this,

Paul


#2

Check out https://www.ory.sh/docs/1-hydra/2-overview/3-access-control#multi-tenant-systems


#3

Hi, tnx for the quick response.

I had missed that bit in the docs, but having read it now, I don’t think it answers my questions (or I might just not understand the docs).

How does what is described under that multi-tenant-systems link help in redirecting to the proper app server instance in the consent flow?

Paul


#4

I was in a hurry and did only read the title :slight_smile:

I’ve read somewhere that it is not advised to have a single Hydra instance for all tenants, so then it would be a Hydra instance per tenant? Is this realy the best practise, cause I feel that being quite a bit overhead.

Really depends on your needs of isolation. Having one instance is fine if you don’t really care that much about isolation. A valid use case for one instance would be an org-wide authZ server where tenants get access credentials from. For multiple instances it would make sense if each org should have its own authZ server. This might make sense where you have dedicated IAM systems in place per tenant.

could we make it work properly, in a sense that the url for the consent app would likely have to be something like my-company.our-webapp.com/consent?.…, where the subdomain part (‘my-company’) would have to somehow be dynamic

Since the implementation is up to you, you could definitely do that. A simple if / switch statement or something like that would solve that easily.


#5

Hi arekkas

Tnx for your explanation.

In our setup we basically have one IAM systems in place per tenant, so as per your suggestion we’d have to run one hydra per instance per tenant.

But I was wondering: 3rd party apps that want to register with us, so tenants can choose to enable them in their instance of our webapp and grant them access to our API, we need to issue those 3rd party apps stuff like the client_id and client_secret, right? And those should be the same client_id/client_secret for every instance of our webapp, I think.

Wouldn’t that be easier/only possible when working with a single Hydra instance?

Regarding whether or not we could make it work and your answer to that that is could be as simple as a switch statement, I have a hard time envisioning that… for example: assume we have a single Hydra instance running and a 3rd party app which is already registered (has a client_id/secret) wants to access our webapp for tenant X, where tenant X’s webap is hosted on x.our-webapp.com. What would the flow then be, which urls would be in play and where would the aforementioned switch statement come in exactly?

One approach than I think might work would be:

  • 3rd party app goes to x.our-webapp.com/oauth2/auth?client_id=…, which we redirect to the Hydra instance
  • Hydra redirects to %%consent_url%%/contenst?consent=…, which is a shared url between all out tenants.
  • the page behing the consent url makes the rest call to Hydra to get more details about the consent request and with those details it is somehow able to determine to which tenant specific url to redirect the User Agent for authentication and authorization

Not being very familiar yet with Hydra, I wonder if the above is feasible, what I’m missing, if I’m not setting myself up for tons of (security) issues this way etc etc.

Some pointers more than appreciated

Paul


#6

If I understand you correctly you want to have different consent apps for every tenant, right? That is very easy to solve:

Please be aware that consent apps are like the most fucking important thing in this set up. Pardon my language, but they are that important. A consent app can impersonate any user. It’s like the universal source of truth. Unless you want your tenants to be able to authenticate users on some other’s tenant behalf, you should really not do this.

Your complete setup feels complicated and specialized. I could probably help you more by knowing about the architecture and use cases, and what you anticipate there. But my time for community help & management is quite limited. If you’d like more sophisticated help than me dropping a few lines in this forums, I recommend checking out our consulting services (link on website, write me a pn, ping me in chat, drop a line to [email protected]). I think they’d make sense in your case. I would also recommend to first play a bit more with Hydra to get a better feeling if it’s the right software for your architecture (it does sound that way but you never know), before you commit to that service.


#7

Hi arekkas,

I hear you loud and clear. Will do some more digging and reviewing and might contact you for additional consulting.

Paul


#8

@paul I think you should use acr_values
See https://www.ory.sh/docs/api/hydra/
API: /oauth2/auth/requests/consent/{challenge}

x-go-name: ACRValues
ACRValues is the Authentication AuthorizationContext Class Reference requested in the OAuth 2.0 Authorization request.
It is a parameter defined by OpenID Connect and expresses which level of authentication (e.g. 2FA) is required.

OpenID Connect defines it as follows:

Requested Authentication AuthorizationContext Class Reference values. Space-separated string that specifies the acr values
that the Authorization Server is being requested to use for processing this Authentication Request, with the
values appearing in order of preference. The Authentication AuthorizationContext Class satisfied by the authentication
performed is returned as the acr Claim Value, as specified in Section 2. The acr Claim is requested as a
Voluntary Claim by this parameter.

https://identityserver.github.io/Documentation/docsv2/endpoints/authorization.html