JKasper11
JKasper11

Reputation: 843

IdentityServer4 within Docker container - Exception IDX20803: Unable to obtain configuration from: 'System.String'

I've been implementing IdentityServer4 to provide authorization for my Angular application. I have this working in my local dev environment, but am running into issues when running in a Docker container. I am able to generate an access token via the /connect/token endpoint, but when I attempt to access a protected API using the token I get the following exception:

System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'. System.IO.IOException: IDX20804: Unable to retrieve document from: 'System.String' System.Net.Http.HttpRequestException: Cannot assign requested address System.Net.Sockets.SocketException (99): Cannot assign requested address at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)

I thought this might be failing validation somewhere, but I tried setting all of these options to false without any effect:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Authority = this.Configuration.SiteUrl;
        options.RequireHttpsMetadata = this.Configuration.SiteUrl.StartsWith("https://");
                    
        options.TokenValidationParameters = new TokenValidationParameters
        {
            NameClaimType = Claims.Username,
            RoleClaimType = Claims.Role,
            RequireExpirationTime = true,
            ClockSkew = TimeSpan.FromMinutes(1),
            ValidateActor = false,
            ValidateTokenReplay = false,
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateLifetime = false,
            ValidateIssuerSigningKey = false
        };
    });

If it matters, my testing has been with a non-https value for Configuration.SiteUrl both inside and outside of the container so that's not the culprit. I don't really think it's a configuration issue since it's generating tokens successfully and the same code works correctly outside of a Docker container.

Configuration.SiteUrl is set to http://localhost:8077 inside the Docker container. Requests to http://localhost:8077/.well-known/openid-configuration return a proper response. Based on the error message I thought it could potentially be making a request to port 8077 within the container for some reason, but nothing changed when I tried with the setting as http://localhost:80 (since port 80 is used inside the container).

Any help identifying/solving the problem would be greatly appreciated as I've been struggling with this for several hours.

Upvotes: 1

Views: 2165

Answers (1)

JKasper11
JKasper11

Reputation: 843

It turns out I was on the right track in one of my attempts. The issue is that the authority needs to resolve within the container, so it has to use the internal port (which for ASP.NET Core is 80). The issuer should resolve publicly which required an additional setting.

In ConfigureServices:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Authority = this.Configuration.Authority;
        options.RequireHttpsMetadata = this.Configuration.SiteUrl.StartsWith("https://");
                    
        options.TokenValidationParameters = new TokenValidationParameters
        {
            NameClaimType = Claims.Username,
            RoleClaimType = Claims.Role,
            RequireExpirationTime = true,
            ClockSkew = TimeSpan.FromMinutes(1),
            ValidateIssuer = true,
            ValidateAudience = false,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true
        };
    });

In Configure:

services.AddIdentityServer(options => options.IssuerUri = this.Configuration.SiteUrl)
    .AddResourceStore<IdentityResourceStore>()
    .AddClientStore<IdentityClientStore>()
    .AddPersistedGrantStore<IdentityPersistedGrantStore>()
    .AddResourceOwnerValidator<IdentityIResourceOwnerPasswordValidator>()
    .AddProfileService<IdentityProfileService>()
    .AddSecretValidator<IdentitySecretValidator>();

Upvotes: 2

Related Questions