Search code examples
dockerdocker-composessl-certificateidentityserver4docker-network

Identity Server 4 on docker Issue


hi i am new to identity server 4. recently i made simple small project using identity server 4. solution has 3 projects of 1.identityserver4 2.api resource 3.client razor. every thing fine in localhost. but when i try the same project in docker i got problem with identityserver 4. this is the repository of the test project here

Problem
when web app client is started it should redirect to identity server 4 login page which happens with local host. but here i ran into the problem.

NOTE: until now according to searching i reach there may be certificate problem OR networking and DNS issue and i tried some suggested approaches but it wont work or maybe i doing it wrong

1st i tried set the authority address to the container name with port like http://identityserver4:9001 (also for client address which is port 5001) which throws the errors as

SocketException: Connection refused System.Net.Sockets.Socket+AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)

HttpRequestException: Connection refused (identityserver4:9001) System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(string host, int port, HttpRequestMessage initialRequest, bool async, CancellationToken cancellationToken)

IOException: IDX20804: Unable to retrieve document from: 'http://identityserver4:9001/.well-known/openid-configuration'. Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(string address, CancellationToken cancel)

InvalidOperationException: IDX20803: Unable to obtain configuration from: 'http://identityserver4:9001/.well-known/openid-configuration'. Microsoft.IdentityModel.Protocols.ConfigurationManager.GetConfigurationAsync(CancellationToken cancel)

  • In this case the error came from client app.
  • When i shutdown the identityserver4 service and try the client it throws the same error. so it seems totally it could not reach identity server.
  • i tried the defined bridge network in docker-compose as well and i got the same result
  • also i tried http request to http://identityserver4:9001/.well-known/openid-configuration from client (i removed the client authorization & authentication stuff for test this) which throws the Connection refused error in response.

2nd i tried set the authority address to http://identityserver4:80. in this case the client app redirect to identity server 4 identityserver4/connect/authorize but the browser throws

dial tcp: lookup identityserver4 on 127.0.0.11:53: no such host

  • in this case the client passed and redirect to identity server 4
  • http request to http://identityserver4:80/.well-known/openid-configuration from client (i removed the client authorization & authentication stuff for test this) gives the correct response.

i linked the github repository above but for ease i also added mu configuration as below. i try some approaches but this is the BASE CODE from the first attempt.

docker-compose.override.yml

version: '3.4'

services:

  identityserver4:
    container_name: identityserver4
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      
    ports:
      - "9001:80"
    networks:
      - mynet


      
  clientapp:
    container_name: clientapp
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    ports:
      - "5001:80"
    depends_on:
      - identityserver4
    networks:
      - mynet



  apiresource:
    container_name: apiresource
    environment:
      - ASPNETCORE_ENVIRONMENT=Development 
    ports:
      - "8001:80"
    networks:
      - mynet

    

    
networks:
  mynet:
    external: true

Identity Server
client configuration in Config.cs

new Client
    {
         ClientId = "razorClient",
         ClientName = "RAZOR Client App",
         AllowedGrantTypes= GrantTypes.Hybrid,
         RequirePkce = false,
         AllowRememberConsent = false,
         RedirectUris = new List<string>()
         {
             "http://clientapp:80/signin-oidc"
         },
         PostLogoutRedirectUris = new List<string>()
         {
             "http://clientapp:80/signout-callback-oidc"
         },
         ClientSecrets = new List<Secret>
         {
            new Secret("secret".Sha256())
         },
         AllowedScopes = new List<string>()
         {
             IdentityServerConstants.StandardScopes.OpenId,
             IdentityServerConstants.StandardScopes.Profile,
             "MYAPI"

         },
         AllowAccessTokensViaBrowser = true,
         
         
    }

program.cs

using IdentityServer;

var builder = WebApplication.CreateBuilder(args);

Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;

builder.Services.AddControllersWithViews();

builder.Services.AddIdentityServer(options =>
{
    options.IssuerUri = "http://identityserver4:80";
})
    .AddInMemoryClients(Config.Clients)
    .AddInMemoryIdentityResources(Config.IdentityResources)
    //.AddInMemoryApiResources(Config.ApiResources)
    .AddInMemoryApiScopes(Config.ApiScopes)
    .AddTestUsers(Config.TestUsers)
    .AddDeveloperSigningCredential();


var app = builder.Build();

if (!app.Environment.IsDevelopment())
{


    app.UseHttpsRedirection();


}



app.UseStaticFiles();
app.UseRouting();


app.UseIdentityServer();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapDefaultControllerRoute();
});

app.Run();

Client APP

program.cs

using ClientApp.Data;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Mvc.Authorization;

var builder = WebApplication.CreateBuilder(args);

Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;


builder.Services.AddHttpClient();

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();



builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{

    options.Authority = "http://identityserver4:80";
    options.MetadataAddress = "http://identityserver4:80/.well-known/openid-configuration";

    
    //options.BackchannelHttpHandler = new HttpClientHandler
    //{
    //    ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
    //};

    options.RequireHttpsMetadata = false;

    options.ClientId = "razorClient";
    options.ClientSecret = "secret";
    options.ResponseType = "code id_token";

    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("MYAPI");

    options.SaveTokens = true;

    options.GetClaimsFromUserInfoEndpoint = true;

});


builder.Services.AddMvcCore(options =>
{
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
    options.Filters.Add(new AuthorizeFilter(policy));
});



var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");

    app.UseHttpsRedirection();
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();


app.UseAuthentication();
app.UseAuthorization();


app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

Solution

  • i got the solution

    Description

    the problem is the container communication. when running the project on localhost (not on docker) every thing is set to localhost:port address including authority address of is4. the app is authorized or redirect to login page simply. but in docker env the authority have to addressed based on docker inter-communication address ( local host is unknown here which leads to connection refused ) which is known by docker containers network but not machine localhost. so in that case the authority of is4 works but when it comes to redirect to login page ( identity server 4 UI ) based on authority address that address is unknown by local machine so it throws DNS error. so according to @Dimitris Maragkos answer i set the base addresses to local machine Ip address like

    options.Authority= "http://192.168.8.202:9001"

    including the client and api relevant required addresses.