Internal authority URL with OpenID Connect in docker for ASP.NET Core
When setting up OpenID Connect with ASP.NET Core in a docker container environment, you may encounter issues with the public authority URL being not accessible inside of the container, causing the setup to fail.
In my test case, it's a Sitecore 10.1 XP environment with Sitecore Identity. Internal Identity URL is http://id but the external Identity URL is https://identity.clientname.com.
This is only one of the possible solutions.
In summary, this solution is to hijack when requests are made in the application related to OpenID connect, and replace external authority URLs with internal ones.
I am not covering the overall setup of OpenID connect in ASP.NET Core, there are enough articles about it on the internet already.
Create a custom HttpClientHandler like below:
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace Custom
{
/// <summary>
/// Handles all the backend channel communications to Identity and replace any public identity url with internal url
/// </summary>
public class CustomHttpMessageHandler : HttpClientHandler
{
private string _authority { get; set; }
private string _internalAuthority { get; set; }
public CustomHttpMessageHandler(string authority, string internalAuthority)
{
_authority = authority;
_internalAuthority = internalAuthority;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.RequestUri = new Uri(request.RequestUri.OriginalString.Replace(_authority, _internalAuthority));
return base.SendAsync(request, cancellationToken);
}
}
}
In the startup.cs, replace the default BackchannelHttpHandler with the custom one:
...
public void ConfigureServices(IServiceCollection services)
{
var internalAuthority = "http://id";
var authority = "https://identity.clientname.com";
...
services
...
.AddOpenIdConnect(cfg =>
{
cfg.Authority = authority;
...
cfg.RequireHttpsMetadata = false;
cfg.BackchannelHttpHandler = new CustomHttpMessageHandler(authority, internalAuthority);
...
cfg.Events.OnRedirectToIdentityProvider = async context =>
{
if (context.ProtocolMessage.RedirectUri.StartsWith("http://"))
{
context.ProtocolMessage.RedirectUri = context.ProtocolMessage.RedirectUri.Replace("http://", "https://");
}
await Task.FromResult(0);
};
...
}
...
}
...
Replace the URLs, ideally, get them from configurations. Note that the handling of http vs https since internal is normally http and external is https.
After the setup, all the requests inside of docker related to OpenID connect will use the internal URL and browser URLs will be proper public https versions.