Search code examples
c#.net-coreidentityserver4

IDX20803: Unable to obtain configuration from: /.well-known/openid-configuration


I am trying to connect my api service (.net core) to identity (.net core + identityserver4) and I am getting this error message

System.InvalidOperationException: IDX20803: Unable to obtain configuration from...

that's because the identity discovery endpoint expects an additional custom header. I created custom IDocumentRetriever

public class AppHttpDocumentRetriever : HttpDocumentRetriever, IDocumentRetriever

and registered it in Startup

services.AddTransient<IDocumentRetriever, AppHttpDocumentRetriever>();

but it doesn't inject in ConfigurationManager. I don't want to add this custom header to all outbound requests via custom middleware. Are there other approaches to adding a custom header to request to the discovery endpoint?


Solution

  • All requests made in the background are performed using HttpClient. What you can do is inject a HttpMessageHandler into the HttpClient.

    To set your own handler, you can set the BackchannelHttpHandler property.

    like:

    .AddOpenIdConnect(options =>
       {
            options.BackchannelHttpHandler = new BackChannelListener();
             ....
       }
    

    A sample handler that logs the requests is shown below and from that I am sure you can figure out how to add a custom header on the outgoing request.

    namespace Infrastructure
    {
        /// <summary>
        /// Backchannel listener, that will log requests made to our IdentityServer 
        /// Source: IdentityServer in Production training class https://www.tn-data.se
        /// </summary>
        public class BackChannelListener : DelegatingHandler
        {
            public BackChannelListener() : base(new HttpClientHandler())
            {
                Console.WriteLine();
            }
    
            protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                Console.WriteLine("BackChannelListener");
                Console.WriteLine("@@@@ SendASync: " + request.RequestUri);
    
                var sw = new Stopwatch();
                sw.Start();
    
                var result = base.SendAsync(request, cancellationToken);
    
                result.ContinueWith(t =>
                {
                    sw.Stop();
    
                    Console.WriteLine("@@@@ success: " + result.IsFaulted);
                    Console.WriteLine("@@@@ loadtime: " + sw.ElapsedMilliseconds.ToString());
                    Console.WriteLine("@@@@ url: " + request.RequestUri);
    
                    Serilog.Log.Logger.ForContext("SourceContext", "BackChannelListener")
                                      .ForContext("url", request.RequestUri)
                                      .ForContext("loadtime", sw.ElapsedMilliseconds.ToString() + " ms")
                                      .ForContext("success", result.IsCompletedSuccessfully)
                                      .Information("Loading IdentityServer configuration");
                });
    
                return result;
            }
        }
    }