Skip to content

Adds support for multiple custom domains#206

Merged
kailash-b merged 19 commits intomainfrom
feat/SDK-7144-Impl
Apr 9, 2026
Merged

Adds support for multiple custom domains#206
kailash-b merged 19 commits intomainfrom
feat/SDK-7144-Impl

Conversation

@kailash-b
Copy link
Copy Markdown
Contributor

By submitting a PR to this repository, you agree to the terms within the Auth0 Code of Conduct. Please see the contributing guidelines for how to create and submit a high-quality PR for this repo.

Description

This PR adds first-class support for Auth0 multiple custom domains in the ASP.NET Core Authentication SDK. It enables dynamic domain (issuer) resolution per request so that a single application instance can authenticate users against different Auth0 custom domains.

Key aspects of the implementation:

  • Introduces Auth0CustomDomainsOptions with a DomainResolver delegate.
  • Adds Auth0CustomDomainStartupFilter to run early in the pipeline, invoke the configured DomainResolver, and cache the resolved domain in HttpContext.Items under Auth0Constants.ResolvedDomainKey.
  • Adds Auth0CustomDomainsOpenIdConnectConfigurationManager to maintain separate OpenIdConnectConfiguration instances per resolved domain, with independent metadata-address-based caching.
  • Adds Auth0CustomDomainsOpenIdConnectPostConfigureOptions to plug the custom configuration manager into OpenIdConnectOptions, disable static issuer validation, and clear Authority so it is resolved dynamically.
  • Updates authentication/event plumbing (including backchannel logout, sign-out redirects, and token validation flows) to prefer the issuer from the authenticated principal or the resolved domain, and to validate issuers against the value stored in the protected authentication state.

Multiple custom domains are only activated when a DomainResolver is configured.

Testing

  • Unit test cases added for all the new code added.

  • This change adds test coverage for new/changed/fixed functionality

Checklist

  • I have added documentation for new/changed functionality in this PR or in auth0.com/docs
  • All active GitHub checks for tests, formatting, and security are passing
  • The correct base branch is being used, if not main

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment thread tests/Auth0.AspNetCore.Authentication.IntegrationTests/TokenValidationTests.cs Outdated
Comment thread src/Auth0.AspNetCore.Authentication/OpenIdConnectEventsFactory.cs Outdated
Comment thread src/Auth0.AspNetCore.Authentication/AuthenticationBuilderExtensions.cs Outdated
Comment thread tests/Auth0.AspNetCore.Authentication.IntegrationTests/TokenClientTests.cs Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 15 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Auth0.AspNetCore.Authentication/OpenIdConnectEventsFactory.cs
Comment thread src/Auth0.AspNetCore.Authentication/Auth0Constants.cs Outdated
{
var httpContextAccessor = new Mock<IHttpContextAccessor>();
var stateDataFormat = new Mock<ISecureDataFormat<AuthenticationProperties>>();
var httpClient = new HttpClient();
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'HttpClient' is created but not disposed.

Suggested change
var httpClient = new HttpClient();
using var httpClient = new HttpClient();

Copilot uses AI. Check for mistakes.
using var response = await client.SendAsync(req);

var protectedMessage2 =
new HttpRequestMessage(HttpMethod.Get, $"{TestServerBuilder.Host}/{TestServerBuilder.Protected}");
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'HttpRequestMessage' is created but not disposed.

Copilot uses AI. Check for mistakes.
Comment on lines +61 to +65
.ReturnsAsync(new HttpResponseMessage()
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("{\"access_token\":\"new_token\",\"token_type\":\"Bearer\",\"expires_in\":86400}")
});
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'HttpResponseMessage' is created but not disposed.

Copilot uses AI. Check for mistakes.
Comment on lines +107 to +111
.ReturnsAsync(new HttpResponseMessage()
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent("{\"access_token\":\"new_token\",\"token_type\":\"Bearer\",\"expires_in\":86400}")
});
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'HttpResponseMessage' is created but not disposed.

Copilot uses AI. Check for mistakes.
nonce = queryParameters["nonce"];
var state = queryParameters["state"];

var message = new HttpRequestMessage(HttpMethod.Get, $"{TestServerBuilder.Host}/{TestServerBuilder.Callback}?state={state}&nonce={nonce}&code=123");
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'HttpRequestMessage' is created but not disposed.

Suggested change
var message = new HttpRequestMessage(HttpMethod.Get, $"{TestServerBuilder.Host}/{TestServerBuilder.Callback}?state={state}&nonce={nonce}&code=123");
using var message = new HttpRequestMessage(HttpMethod.Get, $"{TestServerBuilder.Host}/{TestServerBuilder.Callback}?state={state}&nonce={nonce}&code=123");

Copilot uses AI. Check for mistakes.
{
var nonce = "";
var configuration = TestConfiguration.GetConfiguration();
var domain = configuration["Auth0:Domain"];
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment to domain is useless, since its value is never read.

Suggested change
var domain = configuration["Auth0:Domain"];

Copilot uses AI. Check for mistakes.
@kailash-b kailash-b force-pushed the feat/SDK-7144-Impl branch from 6dba108 to c51ef46 Compare April 7, 2026 10:38
@kailash-b kailash-b marked this pull request as ready for review April 9, 2026 07:33
@kailash-b kailash-b requested a review from a team as a code owner April 9, 2026 07:33
Copy link
Copy Markdown

@tanya732 tanya732 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants