AspNetCore.Docs/aspnetcore/security/data-protection/consumer-apis/purpose-strings-multitenanc...

27 lines
3.2 KiB
Markdown
Raw Normal View History

2016-10-29 01:35:15 +08:00
---
2017-07-01 07:47:15 +08:00
title: Purpose Strings in ASP.NET Core
2016-10-29 01:35:15 +08:00
author: rick-anderson
description: This document outlines purpose string hierarchy and multi-tenancy as it relates to the ASP.NET Core data protection APIs.
2016-10-29 01:35:15 +08:00
ms.author: riande
manager: wpickett
ms.date: 10/14/2016
ms.topic: article
2016-11-17 08:24:57 +08:00
ms.technology: aspnet
ms.prod: asp.net-core
2016-10-29 01:35:15 +08:00
uid: security/data-protection/consumer-apis/purpose-strings-multitenancy
---
2017-01-24 03:30:06 +08:00
# Purpose hierarchy and multi-tenancy in ASP.NET Core
2016-10-29 01:35:15 +08:00
Since an `IDataProtector` is also implicitly an `IDataProtectionProvider`, purposes can be chained together. In this sense, `provider.CreateProtector([ "purpose1", "purpose2" ])` is equivalent to `provider.CreateProtector("purpose1").CreateProtector("purpose2")`.
2016-10-29 01:35:15 +08:00
This allows for some interesting hierarchical relationships through the data protection system. In the earlier example of [Contoso.Messaging.SecureMessage](purpose-strings.md#data-protection-contoso-purpose), the SecureMessage component can call `provider.CreateProtector("Contoso.Messaging.SecureMessage")` once up-front and cache the result into a private `_myProvide` field. Future protectors can then be created via calls to `_myProvider.CreateProtector("User: username")`, and these protectors would be used for securing the individual messages.
2016-10-29 01:35:15 +08:00
This can also be flipped. Consider a single logical application which hosts multiple tenants (a CMS seems reasonable), and each tenant can be configured with its own authentication and state management system. The umbrella application has a single master provider, and it calls `provider.CreateProtector("Tenant 1")` and `provider.CreateProtector("Tenant 2")` to give each tenant its own isolated slice of the data protection system. The tenants could then derive their own individual protectors based on their own needs, but no matter how hard they try they cannot create protectors which collide with any other tenant in the system. Graphically, this is represented as below.
2016-10-29 01:35:15 +08:00
![Multi tenancy purposes](purpose-strings-multitenancy/_static/purposes-multi-tenancy.png)
2016-10-29 01:35:15 +08:00
>[!WARNING]
2016-12-04 02:36:03 +08:00
> This assumes the umbrella application controls which APIs are available to individual tenants and that tenants cannot execute arbitrary code on the server. If a tenant can execute arbitrary code, they could perform private reflection to break the isolation guarantees, or they could just read the master keying material directly and derive whatever subkeys they desire.
2016-10-29 01:35:15 +08:00
The data protection system actually uses a sort of multi-tenancy in its default out-of-the-box configuration. By default master keying material is stored in the worker process account's user profile folder (or the registry, for IIS application pool identities). But it's actually fairly common to use a single account to run multiple applications, and thus all these applications would end up sharing the master keying material. To solve this, the data protection system automatically inserts a unique-per-application identifier as the first element in the overall purpose chain. This implicit purpose serves to [isolate individual applications](xref:security/data-protection/configuration/overview#per-application-isolation) from one another by effectively treating each application as a unique tenant within the system, and the protector creation process looks identical to the image above.