Cloud applications rarely live inside a single subscription forever. As an organization grows, different teams may own different Azure subscriptions, environments may be separated by business unit, and shared infrastructure can live in a dedicated platform subscription.

That creates a practical infrastructure problem for application developers: an application deployed from one Azure subscription may need to reference resources that belong to another subscription or tenant.

.NET Aspire 13.5 introduces improvements for modeling Azure resources across subscription and tenant boundaries. This makes the AppHost more useful for applications where infrastructure ownership does not follow a single-subscription model.

The important part is understanding what Aspire can model, what Azure still controls, and where permissions become the real constraint.

Why Cross-Tenant Infrastructure Is Difficult

A simple application might have everything in one subscription:

Azure Subscription
|
+-- Resource Group
    |
    +-- Application
    +-- Database
    +-- Storage
    +-- Messaging

An enterprise environment may look more like this:

Tenant A
|
+-- Subscription A
|   |
|   +-- Application
|
+-- Subscription B
    |
    +-- Shared Infrastructure

Tenant B
|
+-- Subscription C
    |
    +-- Shared Service

The application can therefore have dependencies outside the subscription where the application itself is deployed.

This is where resource references become important.

What Is a Cross-Tenant Resource Reference?

A resource reference represents an existing Azure resource that an application needs to consume without necessarily owning or provisioning that resource as part of the application's deployment.

For example:

Application
    |
    +----> Storage Account
    |
    +----> Key Vault
    |
    +----> Service Bus

The application may be deployed from one subscription while the referenced resource belongs somewhere else.

The distinction between resource ownership and resource consumption is important.

The application deployment does not automatically gain permissions merely because a resource is referenced.

How Aspire Fits Into the Architecture

.NET Aspire uses the AppHost as a central place to describe application resources and their relationships.

A simplified model looks like this:

                 AppHost
                    |
        +-----------+-----------+
        |                       |
        v                       v
   Application              Azure Resource
        |                       |
        +-----------> Reference+

The AppHost describes the relationship.

Azure remains responsible for:

This means Aspire should be viewed as an infrastructure modeling layer rather than an authorization bypass.

Cross-Subscription vs Cross-Tenant

These two scenarios are related but should not be treated as identical.

Cross-Subscription

Two subscriptions belong to the same Microsoft Entra tenant.

Tenant
|
+-- Subscription A
|     |
|     +-- Application
|
+-- Subscription B
      |
      +-- Database

Identity and authorization can often be managed within the same organizational identity boundary.

Cross-Tenant

The resources belong to different Microsoft Entra tenants.

Tenant A
|
+-- Application

Tenant B
|
+-- Shared Resource

This introduces additional identity and trust considerations.

The deployment identity needs appropriate access in the target tenant, and the application identity may also need permissions to consume the external resource.

This is fundamentally an Azure identity and authorization problem, not simply an Aspire configuration problem.

Modeling Existing Azure Resources

The general pattern is to distinguish an Azure resource that Aspire manages from one that the application consumes as an existing resource.

Conceptually:

var builder = DistributedApplication.CreateBuilder(args);

var existingStorage = builder.AddAzureStorage(
    "shared-storage");

builder.AddProject<Projects.Api>("api")
       .WithReference(existingStorage);

builder.Build().Run();

The exact resource API and configuration depend on the Azure resource type and the Aspire version being used.

The important architectural concept is the dependency:

API
 |
 +-- requires --> Shared Storage

Rather than embedding resource-specific configuration throughout the application, the dependency is represented centrally.

Why Resource References Matter

Without a centralized infrastructure model, configuration often becomes scattered:

appsettings.json
Environment Variables
CI Variables
Deployment Templates
Secrets
Application Code

This can make it difficult to determine which resource an application actually depends on.

A resource reference provides a more explicit relationship.

For example:

Order API
 |
 +-- PostgreSQL
 |
 +-- Service Bus
 |
 +-- Shared Blob Storage

This improves the readability of the application's infrastructure model.

Identity Is the Critical Part

Cross-tenant access usually becomes difficult at the identity layer.

Suppose an application in Tenant A needs to access a storage account in Tenant B.

The architecture might look like:

Application Identity
       |
       v
Microsoft Entra ID
       |
       v
Tenant B
       |
       v
Storage Account

The application identity must be recognized and authorized appropriately.

Simply adding a resource reference does not grant access.

This distinction should be made explicit when designing the deployment.

Avoid Connection Strings Where Managed Identity Is Appropriate

A common pattern in cloud applications is to put a connection string into configuration:

{
  "Storage": {
    "ConnectionString": "..."
  }
}

This can work, but it introduces secret-management responsibilities.

Where the target Azure service supports Microsoft Entra authentication and the application's identity model permits it, managed identity or workload identity can reduce the need to distribute long-lived credentials.

The application might instead authenticate using a credential chain:

var credential = new DefaultAzureCredential();

var client = new BlobServiceClient(
    new Uri(storageEndpoint),
    credential);

The important production consideration is not simply using DefaultAzureCredential, but ensuring that the deployed identity has exactly the permissions it needs.

Least-Privilege Access

Cross-tenant infrastructure should follow least privilege.

Suppose the application only needs to read blobs.

Do not grant broad administrative permissions when a narrower data-plane role is sufficient.

Think about permissions at multiple levels:

Tenant
  |
  +-- Subscription
        |
        +-- Resource Group
              |
              +-- Resource
                    |
                    +-- Data Plane

The correct permission depends on whether the application needs to manage the resource or merely consume its data.

Configuration Example

A production application can separate resource identity from application behavior.

For example:

public sealed class StorageOptions
{
    public required string Endpoint { get; init; }
}

Then:

builder.Services.Configure<StorageOptions>(
    builder.Configuration.GetSection("Storage"));

The endpoint can come from deployment configuration, while authentication is handled by the application's identity.

This avoids coupling application code to a specific credential format.

Testing Cross-Tenant Dependencies

Do not wait until production to discover an authorization problem.

A useful test environment should reproduce the relevant trust relationship.

Test the following:

TestExpected Result
Application startsPass
External resource resolvesPass
Authentication succeedsPass
Authorized operation succeedsPass
Unauthorized operation failsExpected failure
Resource unavailableGraceful handling
Identity missingClear failure

Testing the negative cases is particularly important.

For example, an application should not silently receive elevated permissions simply because its deployment identity changed.

Common Failure Scenario

Consider this architecture:

Tenant A
|
+-- App Subscription
      |
      +-- API

Tenant B
|
+-- Data Subscription
      |
      +-- Storage

The API starts successfully but receives:

403 Forbidden

The problem may not be the Aspire configuration.

Potential causes include:

This is why debugging should begin by separating configuration problems from identity and networking problems.

Troubleshooting Cross-Tenant Access

403 Forbidden

Check the application's effective identity and target resource permissions.

Do not immediately add broader permissions.

401 Unauthorized

Verify that authentication is actually being performed and that the credential chain resolves to the expected identity.

Resource Not Found

Confirm:

A resource can exist but still be invisible to an identity that lacks appropriate permissions.

Works Locally but Fails in Azure

This is a common identity boundary problem.

Locally, DefaultAzureCredential may use a developer login.

In Azure, it may use a managed or workload identity.

Those identities can have completely different permissions.

Production Deployment Pattern

A clean architecture can look like this:

                 Aspire AppHost
                      |
             Infrastructure Model
                      |
        +-------------+-------------+
        |                           |
        v                           v
 Application Resources       Existing Resources
        |                           |
        v                           v
 Subscription A              Subscription B
                                    |
                                    v
                              Shared Service

For cross-tenant resources:

Subscription A
     |
     v
Application Identity
     |
     +------ Trust / Authorization ------+
                                        |
                                        v
                                   Tenant B
                                        |
                                        v
                                  Azure Resource

Each boundary should be explicit.

Best Practices

Keep Resource Ownership Clear

Document which team or subscription owns each shared resource.

Separate Provisioning From Consumption

An application may consume a resource without being responsible for provisioning it.

Keep those responsibilities clear.

Use Stable Resource References

Avoid scattering resource IDs and endpoints across source files.

Centralize infrastructure configuration.

Use Least Privilege

Grant only the permissions required by the application.

Test the Real Identity

A developer identity is not a substitute for the identity used by the deployed application.

Validate Network Boundaries

Private endpoints, firewalls, virtual networks, and DNS can prevent access even when identity permissions are correct.

Log Useful Identity Information

For troubleshooting, record non-sensitive identity and resource metadata where appropriate.

Never log access tokens, client secrets, or other credentials.

Advantages and Disadvantages

Advantages

Disadvantages

A Practical Adoption Approach

For teams introducing cross-boundary Azure resources into an Aspire application:

  1. Identify every external dependency.

  2. Document the owning subscription and tenant.

  3. Decide whether Aspire provisions or references the resource.

  4. Define the application identity.

  5. Configure least-privilege permissions.

  6. Model the resource relationship in the AppHost.

  7. Test authentication independently.

  8. Test authorization.

  9. Validate network connectivity.

  10. Test the complete deployment from a production-like environment.

This process prevents infrastructure modeling and identity configuration from becoming one large troubleshooting problem.

Conclusion

Cross-subscription and cross-tenant architectures are increasingly common in larger Azure environments. Applications may consume shared databases, storage, messaging systems, or other services that are owned by a separate platform team or subscription.

.NET Aspire 13.5 improves the ability to represent Azure infrastructure relationships in the application model, making these dependencies easier to understand and manage.

However, Aspire does not remove Azure's security boundaries. The most important part of a cross-tenant design remains identity, authorization, and network access.

The strongest implementation is therefore one where the AppHost clearly describes resource dependencies, while Azure identity and access controls enforce who can actually use those resources. That separation makes the architecture easier to reason about, test, and operate in production.