18
Views
3
Comments
[Microsoft Login Connector Core] MS Login Connector Core modification for multitenancy
microsoft-login-connector-core
Service icon
Forge asset by MS Login Connector Team
Application Type
Reactive

Hello,
Im building a multitenant app. Login method is SSO via MS Login connector. In app, diferent facilites use different tenant, but all facilities have the same AAD tenant. 
 I want to:
1. Have data separated in app for facilities.
2. Have unified and easy to manage SSO login solution.
3. Allow some members to access multiple tenants (ex. IT user or app admin).

After analyzing the login connector, I've identified 2 possible solutions, both requires modifying MSLoginConnectorCore.

Solution 1. I can extend OAuth2Application entity with column OutsystemsTenantId (Tenant Identifier), set it up in MSLoginConnectorManagement and switch tenant in OAuth2_OutsystemsLogin using this column. 
This will require multiple AAD registrations with users separated by facilites, and it will also require different entry points for Login, therefore I think it's less preffered solution.
Solution 2. I can create entity for mapping users to tenants, which will not be multitenant. After login, I'd check email that was used while logging in and check if that email have more than 1 tenant assigned. If yes, I'd have to create some Tenant Selection Screen, where user can manually select to which tenant to log in. If account would have just 1 tenant, then I would use it OAuth2_OutsystemsLogin to switch to given tenant. For me it seems like a better solution.

Is my understanding of the connector correct and Solution 2 will be better? Maybe you have different suggestions or methods how to archieve something like that? And where should be entity for mapping Users<>Tenants located? In the connectorCore itself, or maybe put it in a separate module? 

2021-09-03 16-45-15
Gonçalo Borrêga

Hi Mateusz,

We've built a multitenant solution as well. Some tips:

  1. Use multitenancy for true and complete isolation. 
    1. Forget admins/IT for a moment. If a business user should be able to access data in different tenants, most likely the solution is not really multitenant and you should use roles and query filters instead, as there will be several use cases that are going to be cross-tenant.
  2. For Admins I'd suggest creating a separate application (eventually with all app layers as usual).
    1. That application should import the multitenant entities but show the tenant identifier. Only admins use the app; they're able to see (and edit) all data. 
    2. You'll be extra-careful with this application in regards to cross tenant data access, but at least you know it is limited to that application/set of use cases exposed there. 
    3. The standard business requirements are not in this application and that will ensure there is no risk of data leakage except for this super-admin specific application.
  3. This approach dramatically simplifies the requirement for login - if that is the case, one AD login always maps to one OS user, in a single tenant!
    1. A business user logs in and only sees/edits the data in their specific tenant
    2. An admin user logs in to the "Administrators Backoffice" application. They might not even see data in any tenant like a business user would. That is even better for compliance and traceability - support/admin use cases are described and monitored in the admin application
  4. This leaves you with one "new use case": delegation / acting on behalf of.
    1. One admin might "act on behalf of a Tenant X user"
    2. (optional) One business user might "act on behalf of another user in the same tenant".

For this last use case we implement a specific functionality where temporarily, and with extra logging, we switch the user's tenant (programatically). For example, in our "Administrators Backoffice app" our support admins are able to "Switch" to a particular tenant temporarily in the scope of a support case or customer request. There's a "button" to explicitly switch that user's tenant programmatically. They're still "Platform Admins" and can use the full admin console but, for a limited time, they can also use the end-user business application and perform some activities as a regular user. The tenant switch logic also assigns them roles in the end user application for that particular tenant when they do the switch, and removes them when they revert back to admins.

Notice that this is quite limited in time, and from an auditing perspective it might make sense to track this "delegated mode" (e.g. created by and updated by columns should have the actual user (admin) that performed the action, whereas some higher level information (eg. approved by) should most likely have the user that delegated access in the first place. 

But thinking in this "delegated access" as its own use case will help clarify requirements. And, maybe, you don't even need all of that for your admins... just a way for them to see existing data to troubleshoot a specific aspect. Most admin use cases should be implemented in the "Admin Backoffice" cross-tenant application and data!

I would avoid changing the Authentication connector any way possible. It has one job: to authenticate and identify a person/individual. Everything else should be application logic, roles, and the split between tenant-specific data and use cases, and cross-tenant (admin) use cases.

Hope this helps :-)

GB

UserImage.jpg
Mateusz Chrzanowski

Thank you, that's an intresting approach to users that should have multitenant access and I for sure try to discuss it with business. Data should be separated for facilities, so multitenancy should be there. But I have one problem with setting up the connector itself on multiple tenants:
 I have tested on my personal  environment (Clean connector, new tenants, new registration in AAD). I have created 3 accounts, each on different email. Each email is on different tenant (1 User : 1 Tenant), and each email is only used once (1 Email : 1 User).
When I log in in icognito with different user, there are 2 outcomes, based on "Create OutSystems Account if doesn't exist" boolean in Management. If it's set to true, Connector auto-creates new account (despite having one with identical credentials) on tenant Users.
If it's set to false, then I get authorization error. 

Seems like I need to switch tenant by myself somewhere. Can you suggest where I should do that or what am I missing?

2021-09-03 16-45-15
Gonçalo Borrêga

Without knowing the internals of the connector, I'd say it is not ready to determine the right tenant under which to create the user (with the Create OS Account flag on). It would have to have some sort of "callback" for you to provide your own business logic; or be ready to take on some of the OpenId/Auth parameters to determine the tenant. Don't think it is ready for that, and seems like an edge case not that easy to support (in the core of the component...)

So my guess is that you should allow the connector to create the user (in the default tenant) and, during the login process check "if the user logging in is in the default tenant, run the logic to properly provision them" - 1. determine the correct tenant for the user, change the user's tenant id (in the DB), perform a TenantSwitch, add permissions (under that tenant).

That way you keep the standard connector logic, and on the user's first login they'll be provisioned in the correct tenant. Following logins would bypass the first condition (user is already in their tenant...)

GB

Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.