The Azure SDK team has become aware of a potential risk for developers using multi-tenant applications to access Azure resources. Most applications using multi-tenant applications are safe; however, multi-tenant applications that take user-provided URIs to Azure resources and authenticate via service-to-service authentication may leave their customers vulnerable to unauthorized access. Multi-tenant applications accepting URIs to user-provided resources must properly validate resource ownership to prevent potential leaks.
Multi-tenant applications need to validate resource ownership as recommended below, and in addition, the Azure SDK team is releasing new versions of the Azure Identity libraries to help multi-tenant applications be secure by default and provide some defense in depth.
Affected applications
Multi-tenant applications that accept a user-provided URI to a customer-owned resource need to validate the ownership of that resource. Examples include, but aren’t limited to:
- URIs to Azure data plane services corresponding to customer owned resources
- URIs to other customer owned data sources or applications protected by Azure Active Directory
Resource URIs could be provided through configuration files, command line interfaces (CLIs), or user interfaces. If ownership of the resource isn’t properly validated, an attacker may be able to trick your application into accessing resources in tenants to which they don’t have access.
Recommended actions
All multi-tenant applications accessing user-provided resources should consider the following measures to secure customer provided resource access:
- When immediate resource access is precipitated by a specific user request, consider using On Behalf Of (OBO) authentication. This authentication flow ensures both the user and application have necessary access to the resource.
- If users provide resource URIs for setup or configuration, consider limiting the user’s input to resources in their current tenant or a single registered tenant.
- Applications whose customers require access to resources in multiple tenants should strongly consider creating a unique multi-tenant application per customer to prevent cross customer access.
- Applications using authentication challenge data (
WWW-Authenticate
headers) returned from requests to customer provided resources should validate the requested authority matches a tenant owned by the same customer.
Additional recommended actions
For applications using the Azure SDK, we have provided new versions of the Azure Identity library to ensure multi-tenant applications are secure by default. These updated libraries restrict multi-tenant authentication and provide APIs to configure the tenants from which credentials may acquire tokens. You should update your applications to use any of the packages below or newer:
- .NET: https://www.nuget.org/packages/Azure.Identity/1.7.0
- Java: https://search.maven.org/artifact/com.azure/azure-identity/1.6.0/jar
- JavaScript: https://www.npmjs.com/package/@azure/identity/v/3.0.0
- Python: https://pypi.org/project/azure-identity/1.11.0
These SDK updates alone don’t mitigate the issue, but they do prevent multi-tenant applications from acquiring tokens for arbitrary tenants by default. With these updates applied, applications must configure the tenants from which credentials may acquire tokens. If an SDK client or the application attempts to acquire a token for a tenant not explicitly allowed in the credential configuration, the credential will throw a runtime error.
This new behavior is a runtime breaking change from the previous support for multi-tenant authentication, which provided no such safeguards. The SDK team carefully considered the impact of this breaking change, and determined it was warranted to ensure multi-tenant applications using the Azure Identity library are secure by default. Multi-tenant applications upgrading from earlier versions of the Azure Identity library can consult the following instructions to fix any impacted credentials:
.NET
As of Azure.Identity
1.7.0, the default behavior of credentials supporting multi-tenant authentication has changed. Each of these credentials will throw an AuthenticationFailedException
if the requested TenantId
doesn’t match the tenant ID originally configured on the credential. Apps must now do one of the following things:
- Add all IDs, of tenants from which tokens should be acquired, to the
AdditionallyAllowedTenants
list in the credential options. For example:var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { AdditionallyAllowedTenants = { "<tenant_id_1>", "<tenant_id_2>" } });
- Add
*
to enable token acquisition from any tenant. This configuration provides behavior compatible with previous multi-tenant support. For example:var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { AdditionallyAllowedTenants = { "*" } });
Java
As of azure-identity
1.6.0, the default behavior of credentials supporting multi-tenant authentication has changed. Each of these credentials will throw an ClientAuthenticationException
if the requested tenantId
doesn’t match the tenant ID originally configured on the credential. Apps must now do one of the following things:
- Add all IDs, of tenants from which tokens should be acquired, to the
additionallyAllowedTenants
list on the credential builder. For example:DefaultAzureCredential defaultAzureCredential = new DefaultAzureCredentialBuilder() .additionallyAllowedTenants("<tenant_id_1>", "tenant_id_2>") .build();
- Add
*
to enable token acquisition from any tenant. This is the original behavior and is compatible with versions 1.4.0 through 1.5.5. For example:DefaultAzureCredential defaultAzureCredential = new DefaultAzureCredentialBuilder() .additionallyAllowedTenants("*") .build();
JavaScript
As of @azure/identity
3.0.0, the default behavior of credentials supporting multi-tenant authentication has changed. Each of these credentials will throw an error if the requested tenantId
doesn’t match the tenant ID originally configured on the credential. Apps must now do one of the following things:
- Add all IDs, of tenants from which tokens should be acquired, to the
additionallyAllowedTenants
array in the credential options. For example:const credential = new DefaultAzureCredential({ additionallyAllowedTenants: ["<tenant_id_1>", "<tenant_id_2>"] });
- Add
*
to enable token acquisition from any tenant, which is the original behavior. For example:const credential = new DefaultAzureCredential({ additionallyAllowedTenants: ["*"] });
Python
Behavioral change to credential types supporting multi-tenant authentication
As of azure-identity
1.11.0, the default behavior of credentials supporting multi-tenant authentication has changed. Each of these credentials will throw an ClientAuthenticationError
if the requested tenant_id
doesn’t match the tenant ID originally configured on the credential. Apps must now do one of the following things:
- Add all IDs, of tenants from which tokens should be acquired, to the
additionally_allowed_tenants
list in the credential options. For example:
credential = DefaultAzureCredential(additionally_allowed_tenants = ["<tenant_id_1>", "<tenant_id_2>"])
- Add
*
to enable token acquisition from any tenant. This is the original behavior and is compatible with previous versions supporting multi tenant authentication. For example:
credential = DefaultAzureCredential(additionally_allowed_tenants=['*'])
Summary
Make sure your application validates that all user-provided URIs to Azure resources are owned by the customer supplying them to avoid unauthorized cross tenant access. Update your Azure Identity package references to the latest package versions to ensure your application is secure by default against unauthorized cross tenant access. Update credentials used in your application which require multi-tenant access to specify any additional tenants the credential may access. For more information on impacted credential types, see the release notes for the language specific Azure Identity library referenced by your application.
Any references architect or use case?
Is team coordinating releases of Microsoft libraries that consume these dependencies with any special urgency?