title: ASP.NET Core Web API client does not trust self-signed certificate used by the Identity Server instance
body: <p>This is a follow up of <a href="https://stackoverflow.com/questions/61997345/how-to-allow-https-connections-from-both-localhost-and-container-towards-an-asp/62060315#62060315">this question</a>.</p>
  <p>I have generated and trusted a self-signed certificate using the following script:</p>
  <pre><code>#create a SAN cert for both host.docker.internal and localhost
  #$cert = New-SelfSignedCertificate -DnsName &quot;host.docker.internal&quot;, &quot;localhost&quot; -CertStoreLocation &quot;cert:\LocalMachine\Root&quot; 
  # does not work: New-SelfSignedCertificate : A new certificate can only be installed into MY store.
  $cert = New-SelfSignedCertificate -DnsName &quot;host.docker.internal&quot;, &quot;localhost&quot; -CertStoreLocation cert:\localmachine\my
  
  #export it for docker container to pick up later
  $password = ConvertTo-SecureString -String &quot;password_here&quot; -Force -AsPlainText
  Export-PfxCertificate -Cert $cert -FilePath &quot;$env:USERPROFILE\.aspnet\https\aspnetapp.pfx&quot; -Password $password
  
  # trust it on your host machine
  $store = New-Object System.Security.Cryptography.X509Certificates.X509Store [System.Security.Cryptography.X509Certificates.StoreName]::Root,&quot;LocalMachine&quot;
  $store.Open(&quot;ReadWrite&quot;)
  $store.Add($cert)
  $store.Close()
  </code></pre>
  <p>When accessing <code>https://host.docker.internal:5500/.well-known/openid-configuration</code> and <code>https://localhost:5500/.well-known/openid-configuration</code> on the host machine, it works as expected (certificate is OK).</p>
  <p>However, the Web API application running in the container is not happy with it:</p>
  <pre><code>web_api          | System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://host.docker.internal:5500/.well-known/openid-configuration'.
  web_api          |  ---&gt; System.IO.IOException: IDX20804: Unable to retrieve document from: 'https://host.docker.internal:5500/.well-known/openid-configuration'.
  web_api          |  ---&gt; System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
  web_api          |  ---&gt; System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
  web_api          |    at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
  </code></pre>
  <p>The docker-compose file for the API is the following (relevant parts only):</p>
  <pre><code>  web.api:
      image: web_api_image
      build: 
        context: .
        dockerfile: ProjectApi/Dockerfile
      environment: 
        - ASPNETCORE_ENVIRONMENT=ContainerDev 
      container_name: web_api
      ports:
        - &quot;5600:80&quot;
      networks:
        - backend
        - data_layer
      depends_on:
        - identity.server
        - mssqlserver
        - web.cache
  
    identity.server:
      image: identity_server_image
      build: 
        context: .
        dockerfile: MyProject.IdentityServer/Dockerfile
      environment: 
        - ASPNETCORE_ENVIRONMENT=ContainerDev 
        - ASPNETCORE_URLS=https://+:443;http://+:80
        - ASPNETCORE_Kestrel__Certificates__Default__Password=password_here
        - ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
      volumes:
        - ~/.aspnet/https:/https:ro
      container_name: identity_server
      ports:
        - &quot;5500:443&quot;
        - &quot;5501:80&quot;
      networks:
        - backend
        - data_layer
      depends_on:
        - mssqlserver
  </code></pre>
  <p>How can I make this work?</p>
  <hr>
  <p>The call towards the identity server is done by setting up the security in API client to use it (no explicit HTTPS call):</p>
  <pre><code>/// &lt;summary&gt;
  /// configures authentication and authorization
  /// &lt;/summary&gt;
  /// &lt;param name=&quot;services&quot;&gt;&lt;/param&gt;
  /// &lt;param name=&quot;configuration&quot;&gt;&lt;/param&gt;
  public static void ConfigureSecurity(this IServiceCollection services, IConfiguration configuration)
  {
      string baseUrl = configuration.GetSection(&quot;Idam&quot;).GetValue&lt;string&gt;(&quot;BaseUrl&quot;);
      Console.WriteLine($&quot;Authentication server base URL = {baseUrl}&quot;);
  
      services.AddAuthentication(options =&gt;
      {
          options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
          options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
      }).AddJwtBearer(o =&gt;
      {
          o.MetadataAddress = $&quot;{baseUrl}/.well-known/openid-configuration&quot;;
          o.Authority = &quot;dev_identity_server&quot;;
          o.Audience = configuration.GetSection(&quot;Idam&quot;).GetValue&lt;string&gt;(&quot;Audience&quot;);
          o.RequireHttpsMetadata = false;
      });
  
      services.AddAuthorization();
  }
  </code></pre>
  <hr>
  <h3>Identity server configuration</h3>
  <pre><code>public void ConfigureServices(IServiceCollection services)
  {
      string connectionStr = Configuration.GetConnectionString(&quot;Default&quot;);
      Console.WriteLine($&quot;[Identity server] Connection string = {connectionStr}&quot;);
  
      services.AddDbContext&lt;AppIdentityDbContext&gt;(options =&gt; options.UseSqlServer(connectionStr));
  
      services.AddTransient&lt;AppIdentityDbContextSeedData&gt;();
  
  
      services.AddIdentity&lt;AppUser, IdentityRole&gt;()
          .AddEntityFrameworkStores&lt;AppIdentityDbContext&gt;()
          .AddDefaultTokenProviders();
  
      services.AddIdentityServer(act =&gt;
          {
              act.IssuerUri = &quot;dev_identity_server&quot;;
          })
          .AddDeveloperSigningCredential()
          // this adds the operational data from DB (codes, tokens, consents)
          .AddOperationalStore(options =&gt;
          {
              options.ConfigureDbContext = builder =&gt; builder.UseSqlServer(Configuration.GetConnectionString(&quot;Default&quot;));
              // this enables automatic token cleanup. this is optional.
              options.EnableTokenCleanup = true;
              options.TokenCleanupInterval = 30; // interval in seconds
          })
          //.AddInMemoryPersistedGrants()
          .AddInMemoryIdentityResources(Config.GetIdentityResources())
          .AddInMemoryApiResources(Config.GetApiResources())
          .AddInMemoryClients(Config.GetClients(Configuration))
          .AddAspNetIdentity&lt;AppUser&gt;();
  
      services.AddDataProtection()
          .PersistKeysToFileSystem(new DirectoryInfo(@&quot;\\UNC-PATH&quot;));
  
      services.AddTransient&lt;IProfileService, IdentityClaimsProfileService&gt;();
  
      services.AddCors(options =&gt; options.AddPolicy(&quot;AllowAll&quot;, p =&gt; p.AllowAnyOrigin()
         .AllowAnyMethod()
         .AllowAnyHeader()));
  
      services.AddMvc(options =&gt;
      {
          options.EnableEndpointRouting = false;
      }).SetCompatibilityVersion(CompatibilityVersion.Latest);
  }
  
  // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  public static void Configure(IApplicationBuilder app, IWebHostEnvironment env, 
      ILoggerFactory loggerFactory, AppIdentityDbContextSeedData seeder)
  {
      seeder.SeedTestUsers();
      IdentityModelEventSource.ShowPII = true;
  
      if (env.IsDevelopment())
      {
          app.UseDeveloperExceptionPage();
      }
  
      app.UseExceptionHandler(builder =&gt;
      {
          builder.Run(async context =&gt;
          {
              context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
              context.Response.Headers.Add(&quot;Access-Control-Allow-Origin&quot;, &quot;*&quot;);
  
              var error = context.Features.Get&lt;IExceptionHandlerFeature&gt;();
              if (error != null)
              {
                  context.Response.AddApplicationError(error.Error.Message);
                  await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false);
              }
          });
      });
  
      // app.UseHttpsRedirection();
  
      app.UseStaticFiles();
      app.UseCors(&quot;AllowAll&quot;);
      app.UseIdentityServer();
  
      app.UseMvc(routes =&gt;
      {
          routes.MapRoute(
              name: &quot;default&quot;,
              template: &quot;{controller=Home}/{action=Index}/{id?}&quot;);
      });
  }
  </code></pre>