-
Notifications
You must be signed in to change notification settings - Fork 161
Multi tenant: Admin access tenant data
Version 2.2.0 and above of the AuthP library contain a feature called link to tenant data that allows a suitably approved user to obtain the DataKey
of a tenant and make that DataKey
adds or replaces the user's DataKey
while the user is linked. A linked user can now access the other tenant's data.
The main use of this feature is to allow an app user (see definition of an app user in the NOTE) to get access to tenant's data. Typically a customer support user would use this feature to help tenant users who have problems, where seeing the data and features in the same way as the tenant user.
NOTE: There is also second usage in hierarchical multi-tenant applications where users at a higher level can link to the data in one of the layer below them. But at this time I am not going to describe this use at the moment.
To use the link to tenant data feature you need to:
- Turn on the feature during the registration of the AuthP library.
- Add features to your application:
- Code to start linking to a tenant's data
- Code to stop linking to a tenant's data
- Code to tell the user is linked to a tenant
- Set up a AuthP customer support user.
NOTE: Example3 uses the link to tenant data feature and provides an excellent example of how you might add this feature to your own application.
You have to set up two AuthPermissionsOptions
parameters:
- Set the
LinkToTenantType
parameter toLinkToTenantTypes.OnlyAppUsers
- Set the
EncryptionKey
parameter with a string of at least 16 characters to use when encrypting / decrypting data used in the link to tenant data feature. This should be private so its typically taken from your appsettings so that your production encryption key can be set by the production system.
The code below shows this part of your regionalisation of the AuthP's library.
services.RegisterAuthPermissions<Example3Permissions>(options =>
{
options.TenantType = TenantTypes.SingleLevel;
options.LinkToTenantType = LinkToTenantTypes.OnlyAppUsers;
options.EncryptionKey = _configuration[nameof(AuthPermissionsOptions.EncryptionKey)];
options.AppConnectionString = connectionString;
options.PathToFolderToLock = _env.WebRootPath;
})
// ... other registration code left out
You need to add commands to turn on the data linking, with the tenantId of the tenant you want to link to, and another to turn off the linking when the user has finished, or they log out.
Typically, the customer support will have access to the list of tenants, and each tenant has a “Access Data” link that starts linking when clicked. The screenshot below was taken from Example3 with the "AppSupport@g1.com" user logged in.
You then have to create an ASP.NET Core action to call the ILinkToTenantDataService
's StartLinkingToTenantDataAsync
method. This action code below will start the linking to the tenant who's primary key is equal to the id
.
[HasPermission(Example3Permissions.TenantAccessData)]
public async Task<IActionResult> StartAccess([FromServices] ILinkToTenantDataService service, int id)
{
var currentUser = User.GetUserIdFromUser();
var status = await service.StartLinkingToTenantDataAsync(currentUser, id);
return status.HasErrors
? RedirectToAction(nameof(ErrorDisplay),
new { errorMessage = status.GetAllErrors() })
: RedirectToAction(nameof(Index), new { message = status.Message });
}
You also need a way to stop linking to a tenant's data. The ILinkToTenantDataService
's method for that is called StopLinkingToTenant
. The action code below shows what this would look like.
public IActionResult StopAccess([FromServices] ILinkToTenantDataService service, bool gotoHome)
{
var currentUser = User.GetUserIdFromUser();
service.StopLinkingToTenant();
return gotoHome
? RedirectToAction(nameof(Index), "Home")
: RedirectToAction(nameof(Index), new { message = "Finished linking to tenant's data" });
}
NOTE: the gotoHome
is used when someone logs out - see the next section.
The user needs to know that they are linked to a tenant's data, especially if their Roles allow them to create, update or delete data in that tenant (see next section on this). There is a method called GetNameOfLinkedTenant
, which returns the name of the tenant the user is linked to, or null if the user isn't linked to the tenant's data. You can use this to tell the user if they are linked.
In the Example3 ASP.NET Core MVC design I injected the ILinkToTenantDataService
into the _Layout.cshtml file and added some Razor code to tell the user they are linked to a tenant's data, and provide link that will stop the linking to a tenant's data (plus code to stop linked if the user logs out).
NOTE: For this to work you need to add the code @inject ILinkToTenantDataService LinkToTenantDataService
at the top of the "_Layout.cshtml" file.
<div class="container">
<main role="main" class="pb-3">
<div class="text-danger">
@{
var tenantName = LinkToTenantDataService.GetNameOfLinkedTenant();
if (tenantName != null)
{
if (!User.Identity.IsAuthenticated)
{
<script>
window.location.replace(
"@Url.Action("StopAccess", "Tenant", new { gotoHome = true }) ");
</script>
}
<div>
Be careful! You are currently linked to the <strong>@tenantName</strong> tenant's data.
<a class="btn btn-outline-primary btn-sm"
asp-area="" asp-controller="Tenant" asp-action="StopAccess">Stop Linking</a>
</div>
}
}
</div>
@RenderBody()
</main>
</div>
Note the code that detects that a) the user is linking to a tenant's data AND b) that user has logged out. In that case it calls the StopAccess action with gotoHome
set to true
. This will stop the linking on log out.
This figure below shows the customer support user with email "AppSupport@g1.com` logged in and is linked to the 4U Inc. tenant data. Note the "be careful..." banner and the "Stop Linking" button.
Any app-level (i.e. user not linked to a tenant) can use the link to tenant data as long as they have the correct Roles / Permissions to start and stop methods in the ILinkToTenantDataService
service. Having said that its useful for the user linking to the tenant's data also has the Roles / Permissions that the tenant users have, so that the user can use the tenant's features, otherwise linking to the data isn't very useful.
If you have a small team, you might add access to the tenant features to the App Admin users. In larger applications, where you need dedicated customer support team you could set up a customer support user which access to some of the AuthP admin services, but maybe not admin features that could break things, plus the tenant features.
For instance in the Example3 application I created a user called "AppSupport@g1.com" which had the following Roles / Permission
- A Role called "App Support", with Permissions that are read-only views or Roles, Tenants and Users, plus the Permission to start / stop linking to a tenant's data.
- Added the "Tenant User" Role, which allows the user to use the features that the tenant user's have. This means the "AppSupport@g1.com" user can access all the features that a tenant user would use.
- Intro to multi-tenants (ASP.NET video)
- Articles in date order:
- 0. Improved Roles/Permissions
- 1. Setting up the database
- 2. Admin: adding users and tenants
- 3. Versioning your app
- 4. Hierarchical multi-tenant
- 5. Advanced technique with claims
- 6. Sharding multi-tenant setup
- 7. Three ways to add new users
- 8. The design of the sharding data
- 9. Down for maintenance article
- 10: Three ways to refresh claims
- 11. Features of Multilingual service
- 12. Custom databases - Part1
- Videos (old)
- Authentication explained
- Permissions explained
- Roles explained
- AuthUser explained
- Multi tenant explained
- Sharding explained
- How AuthP handles sharding
- How AuthP handles errors
- Languages & cultures explained
- JWT Token refresh explained
- Setup Permissions
- Setup Authentication
- Startup code
- Setup the custom database feature
- JWT Token configuration
- Multi tenant configuration
- Using Permissions
- Using JWT Tokens
- Creating a multi-tenant app
- Supporting multiple languages
- Unit Test your AuthP app