Skip to content

Commit ec57fb6

Browse files
committed
Updates ReadMe and Examples.md
1 parent 7c96772 commit ec57fb6

2 files changed

Lines changed: 192 additions & 4 deletions

File tree

EXAMPLES.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- [Organizations](#organizations)
77
- [Extra parameters](#extra-parameters)
88
- [Roles](#roles)
9+
- [Multiple Custom Domains](#multiple-custom-domains)
910
- [Backchannel Logout](#backchannel-logout)
1011
- [Blazor Server](#blazor-server)
1112

@@ -314,6 +315,161 @@ public IActionResult Admin()
314315
}
315316
```
316317

318+
## Multiple Custom Domains
319+
320+
The SDK supports scenarios where a single application needs to authenticate users against **multiple Auth0 tenants** or **custom domains**. This is useful for multi-tenant SaaS applications where each customer has their own Auth0 tenant.
321+
322+
### Basic Configuration
323+
324+
Enable Multiple Custom Domains by calling `WithCustomDomains()` and providing a `DomainResolver` function:
325+
326+
```csharp
327+
services.AddAuth0WebAppAuthentication(options =>
328+
{
329+
options.Domain = Configuration["Auth0:Domain"];
330+
options.ClientId = Configuration["Auth0:ClientId"];
331+
})
332+
.WithCustomDomains(options =>
333+
{
334+
options.DomainResolver = httpContext =>
335+
{
336+
var host = httpContext.Request.Host.Host;
337+
338+
// Route to different Auth0 tenants based on subdomain
339+
if (host.StartsWith("tenant-a."))
340+
{
341+
return Task.FromResult("tenant-a.us.auth0.com");
342+
}
343+
344+
if (host.StartsWith("tenant-b."))
345+
{
346+
return Task.FromResult("tenant-b.us.auth0.com");
347+
}
348+
349+
// Default domain
350+
return Task.FromResult("your-default-domain.us.auth0.com");
351+
};
352+
});
353+
```
354+
355+
### Configuring the DomainResolver
356+
357+
The `DomainResolver` function receives the `HttpContext` and returns the Auth0 domain as a string. You can inspect any aspect of the HTTP request. The resolver can perform simple lookups or complex operations like querying a database:
358+
359+
```csharp
360+
options.DomainResolver = httpContext =>
361+
{
362+
// Option 1: Based on subdomain
363+
var host = httpContext.Request.Host.Host;
364+
var subdomain = host.Split('.')[0];
365+
return Task.FromResult($"{subdomain}.us.auth0.com");
366+
367+
// Option 2: Based on path
368+
var path = httpContext.Request.Path.Value;
369+
if (path.StartsWith("/tenant-a"))
370+
return Task.FromResult("tenant-a.us.auth0.com");
371+
372+
// Option 3: Based on custom header
373+
var tenantHeader = httpContext.Request.Headers["X-Tenant-Id"].FirstOrDefault();
374+
return Task.FromResult($"{tenantHeader}.us.auth0.com");
375+
376+
// Option 4: Based on cookie
377+
var tenantCookie = httpContext.Request.Cookies["tenant"];
378+
return Task.FromResult($"{tenantCookie}.us.auth0.com");
379+
};
380+
381+
// Option 5: Complex resolution with database lookup
382+
options.DomainResolver = async httpContext =>
383+
{
384+
var host = httpContext.Request.Host.Host;
385+
var tenantId = host.Split('.')[0];
386+
387+
// Look up tenant configuration from database
388+
var tenantService = httpContext.RequestServices
389+
.GetRequiredService<ITenantService>();
390+
var tenant = await tenantService.GetTenantAsync(tenantId);
391+
392+
return tenant?.Auth0Domain ?? "default.us.auth0.com";
393+
};
394+
```
395+
396+
### Caching Configuration
397+
398+
Control how OpenID Connect configurations are cached for each domain using `ConfigurationManagerCache`.
399+
400+
#### MemoryConfigurationManagerCache (Default)
401+
402+
Caches configurations in memory with configurable size and expiration:
403+
404+
```csharp
405+
.WithCustomDomains(options =>
406+
{
407+
options.DomainResolver = httpContext => { /* ... */ };
408+
409+
options.ConfigurationManagerCache = new MemoryConfigurationManagerCache(
410+
maxSize: 100, // Maximum number of domains to cache
411+
slidingExpiration: TimeSpan.FromHours(1) // Optional: cache entries expire after 1 hour of inactivity
412+
);
413+
});
414+
```
415+
416+
#### NullConfigurationManagerCache
417+
418+
Disables caching entirely (not recommended for production):
419+
420+
```csharp
421+
.WithCustomDomains(options =>
422+
{
423+
options.DomainResolver = httpContext => { /* ... */ };
424+
options.ConfigurationManagerCache = new NullConfigurationManagerCache();
425+
});
426+
```
427+
428+
#### Custom Cache Implementation
429+
430+
Implement `IConfigurationManagerCache` for custom caching strategies (e.g., Redis, distributed cache):
431+
432+
```csharp
433+
public class RedisConfigurationManagerCache : IConfigurationManagerCache
434+
{
435+
private readonly IDistributedCache _cache;
436+
437+
public RedisConfigurationManagerCache(IDistributedCache cache)
438+
{
439+
_cache = cache;
440+
}
441+
442+
public IConfigurationManager<OpenIdConnectConfiguration> GetOrCreate(
443+
string metadataAddress,
444+
Func<string, IConfigurationManager<OpenIdConnectConfiguration>> factory)
445+
{
446+
// Implement Redis-based caching logic
447+
}
448+
449+
public void Clear() => _cache.Remove("oidc-configs");
450+
public void Dispose() { }
451+
}
452+
453+
// Usage
454+
.WithCustomDomains(options =>
455+
{
456+
options.DomainResolver = httpContext => { /* ... */ };
457+
options.ConfigurationManagerCache = new RedisConfigurationManagerCache(distributedCache);
458+
});
459+
```
460+
461+
### Important Considerations
462+
463+
1. **Domain Resolution Timing**: The `DomainResolver` is called early in the request pipeline and the result is cached for the duration of the request.
464+
465+
2. **Callback URLs**: Each Auth0 tenant must have the appropriate callback URLs configured:
466+
- **Allowed Callback URLs**: `https://{your-domain}/callback`
467+
- **Allowed Logout URLs**: `https://{your-domain}/`
468+
469+
3. **Token Validation**: The SDK automatically validates that tokens come from the expected issuer (the domain returned by your `DomainResolver`).
470+
471+
4. **Performance**: Use the default `MemoryConfigurationManagerCache` for most scenarios. The cache significantly reduces the overhead of fetching OIDC configuration for each request.
472+
317473
## Backchannel Logout
318474

319475
Backchannel logout can be configured by calling `WithBackchannelLogout()` when calling `AddAuth0WebAppAuthentication`.

README.md

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ A library based on `Microsoft.AspNetCore.Authentication.OpenIdConnect` to make i
66
![Downloads](https://img.shields.io/nuget/dt/auth0.aspnetcore.authentication)
77
[![License](https://img.shields.io/:license-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT)
88
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/auth0/auth0-aspnetcore-authentication)
9-
![AzureDevOps](https://img.shields.io/azure-devops/build/Auth0SDK/Auth0.AspNetCore.Authentication/8)
9+
[![Build and Test](https://github.com/auth0/auth0-aspnetcore-authentication/actions/workflows/build.yml/badge.svg)](https://github.com/auth0/auth0-aspnetcore-authentication/actions/workflows/build.yml)
1010

1111
:books: [Documentation](#documentation) - :rocket: [Getting Started](#getting-started) - :computer: [API Reference](#api-reference) - :speech_balloon: [Feedback](#feedback)
1212

@@ -15,12 +15,12 @@ A library based on `Microsoft.AspNetCore.Authentication.OpenIdConnect` to make i
1515
- [Quickstart](https://auth0.com/docs/quickstart/webapp/aspnet-core) - our interactive guide for quickly adding login, logout and user information to an ASP.NET MVC application using Auth0.
1616
- [Sample App](https://github.com/auth0-samples/auth0-aspnetcore-mvc-samples/tree/master/Quickstart/Sample) - a full-fledged ASP.NET MVC application integrated with Auth0.
1717
- [Examples](https://github.com/auth0/auth0-aspnetcore-authentication/blob/main/EXAMPLES.md) - code samples for common ASP.NET MVC authentication scenario's.
18-
- [Docs site](https://www.auth0.com/docs) - explore our docs site and learn more about
18+
- [Docs site](https://www.auth0.com/docs) - explore our docs site and learn more about Auth0.
1919

2020
## Getting started
2121
### Requirements
2222

23-
This library supports .NET 6.0 and above.
23+
This library supports .NET 6.0, 7.0, 8.0, and 10.0.
2424

2525
### Installation
2626

@@ -114,6 +114,38 @@ For more code samples on how to integrate the **auth0-aspnetcore-authentication*
114114

115115
> This SDK also works with Blazor Server, for more info see [the Blazor Server section in our examples](https://github.com/auth0/auth0-aspnetcore-authentication/blob/main/EXAMPLES.md#blazor-server).
116116
117+
## Multiple Custom Domains
118+
119+
The SDK supports scenarios where a single application needs to authenticate users against **multiple Auth0 tenants** or **custom domains**. This is useful for multi-tenant SaaS applications where each customer has their own Auth0 tenant.
120+
121+
### Configuration
122+
123+
```csharp
124+
services.AddAuth0WebAppAuthentication(options =>
125+
{
126+
options.Domain = Configuration["Auth0:Domain"];
127+
options.ClientId = Configuration["Auth0:ClientId"];
128+
})
129+
.WithCustomDomains(options =>
130+
{
131+
options.DomainResolver = httpContext =>
132+
{
133+
var host = httpContext.Request.Host.Host;
134+
135+
// Route to different Auth0 tenants based on subdomain
136+
if (host.StartsWith("tenant-a."))
137+
return Task.FromResult("tenant-a.us.auth0.com");
138+
139+
if (host.StartsWith("tenant-b."))
140+
return Task.FromResult("tenant-b.us.auth0.com");
141+
142+
return Task.FromResult("default.us.auth0.com");
143+
};
144+
});
145+
```
146+
147+
For detailed configuration options, caching strategies, and more examples, see the [Multiple Custom Domains Examples](EXAMPLES.md#multiple-custom-domains).
148+
117149
## API reference
118150
Explore public API's available in auth0-aspnetcore-authentication.
119151

@@ -152,4 +184,4 @@ Please do not report security vulnerabilities on the public GitHub issue tracker
152184
</p>
153185
<p align="center">Auth0 is an easy to implement, adaptable authentication and authorization platform. To learn more checkout <a href="https://auth0.com/why-auth0">Why Auth0?</a></p>
154186
<p align="center">
155-
This project is licensed under the MIT license. See the <a href="https://github.com/auth0/auth0-aspnetcore-authentication/blob/main/LICENSE"> LICENSE</a> file for more info.</p>
187+
This project is licensed under the MIT license. See the <a href="https://github.com/auth0/auth0-aspnetcore-authentication/blob/main/LICENSE">LICENSE</a> file for more info.</p>

0 commit comments

Comments
 (0)