# Help with b2b multi-tenant SPA & multi product APIs

**URL:** <https://community.auth0.com/t/help-with-b2b-multi-tenant-spa-multi-product-apis/39871>\
**Category:** Get Help\
**Tags:** multi-tenant\
**Created:** [March 24, 2020, 4:27pm UTC](https://community.auth0.com/t/help-with-b2b-multi-tenant-spa-multi-product-apis/39871 "2020-03-24T16:27:20Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![gerardo.zenobi](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/gerardo.zenobi/32/19263_2.png) [@gerardo.zenobi](https://community.auth0.com/u/gerardo.zenobi)\
**Post date:** [March 24, 2020, 4:27pm UTC](https://community.auth0.com/t/help-with-b2b-multi-tenant-spa-multi-product-apis/39871/1 "2020-03-24T16:27:20Z")

</div>

Hi @mathiasconradt. I found your answer in [this post](http://community.auth0.com/t/help-with-multi-tenant-spa-rest-application/38893) about possible ways to go about implementing multi tenancy for that scenario quite helpful!  
However I still have doubts/questions, possibly due to my use case being slightly different. I wanted to know if you could give me a hand in modeling a possible solution and flow to accomplish it.

Let me start with a bit of context. I will try to explain as clear as possible:  
We have multiple APIs mapped in Auth0 each one of them being a completely different **Product** (api\_1, api\_2, …) that customer organisations can buy separately or in combination. These APIs can be accessed directly by M2M clients or be consumable by users via an SPA that we have.  
For each API there are roles with their associated permissions: **USER\_PRODUCT\_API\_1** , **ADMIN\_PRODUCT\_API\_1** , **USER\_PRODUCT\_API\_2** and so on.

A user could belong to multiple organisations. Also this user might have different roles in each organisation. I understand this can only me mapped through his/her _app\_metadata_ (and not through through the normal dashboard) right ?, something like:

```json
{
  "tenants": [
    {
      "name": "org_1",
      "roles": ["USER_PRODUCT_API_1", "USER_PRODUCT_API_2"]
    },
    {
      "name": "org_2",
      "roles": ["ADMIN_PRODUCT_API_1"]
    }
  ]
}

```

Then, to model we would most likely have an SPA app per organisation and 1 database connection for all users. We would map in each SPA app metadata which Products that organisation has access to. (correct me otherwise if other approach based on the above is recommended)

So how would we then do the following:

- user logs in and
- he is presented with the choice to select one of the organisations he belongs to (or not if only one)
- the SPA then requests tokens **only** for authorised API audiences (those associated with the organisation)
- for each audience token request the correct role should be applied:  
if user selected `org_1` then permissions associated with **USER\_PRODUCT\_API\_1** should be put in the token when requesting token for audience _PRODUCT\_API\_1_
- each access token is enriched with further information regarding the organisation chosen (e.g. which datasets this organisation can see based on a call to an external service)
- the SPA makes requests to the respective APIs with their respective token.

to correctly log in and authorise a user to interact via our SPA with all the different products and correct permissions respectively ?

Thanks in advance for your help.

Gerardo.

---

<div class="post-metadata">

**Author:** ![mathiasconradt](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/mathiasconradt/32/12758_2.png) [@mathiasconradt](https://community.auth0.com/u/mathiasconradt)\
**Post date:** [March 25, 2020, 10:36am UTC](https://community.auth0.com/t/help-with-b2b-multi-tenant-spa-multi-product-apis/39871/2 "2020-03-25T10:36:45Z")

</div>

Hi @gerardo.zenobi,

> We have multiple APIs mapped in Auth0 each one of them being a completely different Product

Note that an access token can only be issued for one audience (API), if you register them as separate APIs in Auth0.  
An option is to represent them as one logical API.  
See [Configure Logical API for Multiple APIs](https://auth0.com/docs/api-auth/tutorials/represent-multiple-apis)

But I think you’re already aware of it, since you used plural here when you said:

> the SPA then requests tokens only for authorised API audiences (those associated with the organisation)

Just to let you know that we have a docs page around that (see above).

* * *

> I understand this can only me mapped through his/her app\_metadata (and not through through the normal dashboard) right ?

As of today, that’s right. There’s no concept or groups or organisations available to the public yet, however note that we’re working on an concept of “organizations” as part of our [RBAC](https://auth0.com/docs/authorization/concepts/rbac) (role-based access control) approach.  
This is planned for sometime in Q2.

**Until then, using the `app_metadata` is a valid approach, and then handle it accordingly in a Rule for example.**

> each access token is enriched with further information regarding the organisation chosen (e.g. which datasets this organisation can see based on a call to an external service)

Yes, you could i.e. add permissions as [custom claims](https://auth0.com/docs/api-auth/tutorials/adoption/scope-custom-claims#custom-claims) into the ID and/or access token via Rule.

* * *

Just to give you an idea what it could look like with groups/organisations available in the future:

There are Roles as you know them…

 ![image](https://global.discourse-cdn.com/auth0/original/3X/1/c/1c5a85dc0aafc6e182b4b390b867cbdb4b145a86.png)

and Groups/Orgs available, which I created as org1\_admins, org1\_users, etc. to which you can assign users…

 ![image](https://global.discourse-cdn.com/auth0/original/3X/2/4/24b41d60c58ce2203751ede664338a314db5f46b.png)

where these groups have the roles assigned based on the products the org purchased.

 ![image](https://global.discourse-cdn.com/auth0/original/3X/d/a/daa630e64ad9df8eec93879a2397fa69435b9925.png)

To each role, there are permissions assigned as per our RBAC approach.

Note that above screenshots are from my own internal test tenant, the [RBAC](https://auth0.com/docs/authorization/concepts/rbac) Groups aren’t publicly available today in tenants.

---

<div class="post-metadata">

**Author:** ![gerardo.zenobi](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/gerardo.zenobi/32/19263_2.png) [@gerardo.zenobi](https://community.auth0.com/u/gerardo.zenobi)\
**Post date:** [March 25, 2020, 5:18pm UTC](https://community.auth0.com/t/help-with-b2b-multi-tenant-spa-multi-product-apis/39871/3 "2020-03-25T17:18:42Z")

</div>

Hi @mathiasconradt, thanks for the rapid response ! Although it is still unclear to me how to go about to implement the scenario.

I wouldn’t be able to implement something similar to **Option C** (from the [original post](http://community.auth0.com/t/help-with-multi-tenant-spa-rest-application/38893)) since in my case, due to the fact that the roles depend on the organisation selected, it will have to be always a multiple step process: meaning I think I am forced to use what you referenced as _Redirect Rules_ unless going for a different option like **Option A** for example.

Then:

If going with **Option D** (1 SPA app, no subdomains):

- user logs in, we validate credentials, check the his/her `app_metadata` to see which orgs he/she belongs to and we redirect to custom UI for him/her to select an organisation. do we pass the organisations as a custom claim in the Id Token or what gets passed to this custom UI ?
- user selects the organisation; authorisation flow continues ( `/continue` ): the selected org value is feed then to the rules engine, how is it passed? also, are we still only talking about ID Token here?
- user is logged in within the SPA and the SPA has received an ID Token (maybe with a claim about the chosen organisation)
- how do the, later on initiated by the SPA, access token requests behave within this scenario? This is the part I am confused as I can’t imagine how a Rule would have access to the organisation selected before since they are not part of the `/continue` flow. Since roles are by organisation we need this information in order to produce the access token.

If going with **Option A** (1 SPA app per organisations, subdomains to manage client id):

is the following more or less correct?

- user logs in through via a particular subdomain providing the `/authorise` endpoint with the proper client id. Organisation is then pre-selected and we have access to it during Rules.
- SPA receives within the ID Token the API audiences this SPA should request access token for.
- SPA can requests access tokens for the APIs: a Rule has access to the client\_id and retrieve the roles associated with the respective organisation from the user `app_metadata`. (?) Do we need to translate them manually into permissions and create the appropriate scope ?
- SPA receives access tokens and calls APIs.

In order to implement option A it is mandatory, and entirely on our side, to manage subdomains ([customerX.app.com](http://customerX.app.com)) to track each client id correct ? or is there other alternative I am missing ?

Thanks again,

Gerardo.

---

<div class="post-metadata">

**Author:** ![gerardo.zenobi](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/gerardo.zenobi/32/19263_2.png) [@gerardo.zenobi](https://community.auth0.com/u/gerardo.zenobi)\
**Post date:** [April 3, 2020, 9:01am UTC](https://community.auth0.com/t/help-with-b2b-multi-tenant-spa-multi-product-apis/39871/4 "2020-04-03T09:01:38Z")

</div>

Hi @mathiasconradt, not sure if you might have missed my response to your answer.

If you have some time I would appreciate your help 🙂

Thanks in advance,

Gerardo.

---

<div class="post-metadata">

**Author:** ![gerardo.zenobi](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/gerardo.zenobi/32/19263_2.png) [@gerardo.zenobi](https://community.auth0.com/u/gerardo.zenobi)\
**Post date:** [April 14, 2020, 9:53am UTC](https://community.auth0.com/t/help-with-b2b-multi-tenant-spa-multi-product-apis/39871/5 "2020-04-14T09:53:20Z")

</div>

**Update**

I managed to implement **Option D**. After credentials have been validated the user is asked to select a tenant if he/she belongs to many (done through Redirect rule). As a result all subsequent `/authorise` calls when requesting for ID and/or access tokens have as a query parameter the organisation the user _is in at the moment_. This is used to manually convert organisation roles into permissions within Rules.

- Does this sound OK ? no security concerns regarding sending the `org` query param ?

However for **Option A** (1 SPA app per organisations, subdomains to manage client id):

- any ideas how it would be possible to perform this _organisation selection_ ? or is it not possible at all given we don’t know which ones are available before user has provided credentials ? He/she would have to land directly on the tenant vanity url ?
- is it is mandatory, and entirely on our side, to manage subdomains ([customerX.app.com](http://customerx.app.com/)) in order to identify each tenant application? or is this partly/fully managed by Auth0 and if so how?

Thanks in advance.

Gerardo.

---

<div class="post-metadata">

**Author:** ![martin.la.rosa](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/martin.la.rosa/32/12776_2.png) [@martin.la.rosa](https://community.auth0.com/u/martin.la.rosa)\
**Post date:** [July 11, 2020, 7:49pm UTC](https://community.auth0.com/t/help-with-b2b-multi-tenant-spa-multi-product-apis/39871/6 "2020-07-11T19:49:36Z")

</div>

Hey @gerardo.zenobi, did you manage to get an answer for option D?

---

<div class="post-metadata">

**Author:** ![gerardo.zenobi](https://sea1.discourse-cdn.com/auth0/user_avatar/community.auth0.com/gerardo.zenobi/32/19263_2.png) [@gerardo.zenobi](https://community.auth0.com/u/gerardo.zenobi)\
**Post date:** [July 15, 2020, 6:46am UTC](https://community.auth0.com/t/help-with-b2b-multi-tenant-spa-multi-product-apis/39871/7 "2020-07-15T06:46:43Z")

</div>

Hi Martin,

No, unfortunately I didn’t get any answer.

Specifically what were you after, just the answer to:

> Does this sound OK ? no security concerns regarding sending the `org` query param ?

or you had a different question ?

Regards,

Gerardo.
