'System.InvalidOperationException: IDX20803: Unable to obtain configuration from (OKTA)

I'm trying to implement the Okta.AspNetCore middleware based on their docs on their GitHub page https://github.com/okta/okta-aspnet/blob/master/docs/aspnetcore-webapi.md but to no avail.

This is the stack trace:

Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[3]
  Exception occurred while processing message.
  System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://company.oktapreview.com/oauth2/aus17ct73zmZrZjbh0h8/.well-known/openid-configuration'.
     at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel)
     at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()

Here is my config in program.cs

using Lamar;
using Lamar.Microsoft.DependencyInjection;
using Microsoft.IdentityModel.Logging;
using Microsoft.OpenApi.Models;
using NCL.StockSupplyChain.Common.Configuration;
using NCL.StockSupplyChain.PurchaseOrder.Web.API;
using NCL.StockSupplyChain.PurchaseOrder.Web.API.Classes;
using NCL.StockSupplyChain.ServiceInventory.Token;
using NCL.StockSupplyChain.ServiceInventory.Workflow;
using Okta.AspNetCore;

var corsPolicyName = "EnableCors";

var builder = WebApplication.CreateBuilder(args);

var logger = builder.Logging.Services.BuildServiceProvider().GetRequiredService<ILogger<Program>>();

IdentityModelEventSource.ShowPII = true;

// use Lamar as DI.
builder.Host.UseLamar()
    .ConfigureContainer<ServiceRegistry>(builder =>
    {
        builder.Scan(x =>
        {
            x.AssembliesFromApplicationBaseDirectory(filter => filter.FullName is not null && filter.FullName.StartsWith("NCL."));
            x.TheCallingAssembly();
            x.RegisterConcreteTypesAgainstTheFirstInterface();
        });
    });

builder.Services.AddControllers()
    .AddJsonOptions(jsonOptions => jsonOptions.JsonSerializerOptions.PropertyNamingPolicy = null);
builder.Services
    .AddRouting(options => options.LowercaseUrls = true)
    .AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "NCL.StockSupplyChain.PurchaseOrder.Web.API", Version = "v1" });
    })
    .AddCors(options =>
    {
        options.AddPolicy(name: corsPolicyName,
            corsBuilder =>
            {
                var allowedOrigins = builder.Configuration.Get<Configuration>().Cors?.AllowedOrigins;

                if (allowedOrigins?.Any() ?? false)
                {
                    corsBuilder.WithOrigins(allowedOrigins.ToArray())
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                }
            });
    })
    .AddHttpClient()
    .Configure<Configuration>(builder.Configuration)
    .Configure<ConnectionStringsConfiguration>(builder.Configuration.GetSection("ConnectionStrings"))
    .Configure<WorkflowConfiguration>(builder.Configuration.GetSection("WorkflowService"))
    .Configure<TokenConfiguration>(builder.Configuration.GetSection("TokenService"))
    .AddLogging()
    .AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = OktaDefaults.ApiAuthenticationScheme;
        options.DefaultChallengeScheme = OktaDefaults.ApiAuthenticationScheme;
        options.DefaultSignInScheme = OktaDefaults.ApiAuthenticationScheme;
    })
    .AddOktaWebApi(new OktaWebApiOptions()
    {
        OktaDomain = "https://company.oktapreview.com",
        AuthorizationServerId = "aus17ct73zmZrZjbh0h8",
        BackchannelHttpClientHandler = new MyLoggingHandler(logger),
    });

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage()
        .UseSwagger()
        .UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "NCL.StockSupplyChain.PurchaseOrder.Web.API"));
}

app.UseHttpsRedirection()
    .UseRouting()
    .UseAuthorization()
    .UseCors(corsPolicyName)
    .UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

await app.RunAsync();

Does anyone know what I could be missing? This has left me scratching my head.



Solution 1:[1]

In the end I got it working with this code:

using Lamar;
using Lamar.Microsoft.DependencyInjection;
using Microsoft.IdentityModel.Logging;
using Microsoft.OpenApi.Models;
using NCL.StockSupplyChain.Common.Configuration;
using NCL.StockSupplyChain.PurchaseOrder.Web.API.Classes;
using NCL.StockSupplyChain.ServiceInventory.Token;
using NCL.StockSupplyChain.ServiceInventory.Workflow;
using Okta.AspNetCore;

var corsPolicyName = "EnableCors";

var builder = WebApplication.CreateBuilder(args);

var logger = builder.Logging.Services.BuildServiceProvider().GetRequiredService<ILogger<Program>>();

// use Lamar as DI.
builder.Host.UseLamar()
    .ConfigureContainer<ServiceRegistry>(builder =>
    {
        builder.Scan(x =>
        {
            x.AssembliesFromApplicationBaseDirectory(filter => filter.FullName is not null && filter.FullName.StartsWith("NCL."));
            x.TheCallingAssembly();
            x.RegisterConcreteTypesAgainstTheFirstInterface();
        });
    });

builder.Services.AddControllers()
    .AddJsonOptions(jsonOptions => jsonOptions.JsonSerializerOptions.PropertyNamingPolicy = null);
builder.Services
    .AddRouting(options => options.LowercaseUrls = true)
    .AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "NCL.StockSupplyChain.PurchaseOrder.Web.API", Version = "v1" });
    })
    .AddCors(options =>
    {
        options.AddPolicy(name: corsPolicyName,
            corsBuilder =>
            {
                var allowedOrigins = builder.Configuration.Get<Configuration>().Cors?.AllowedOrigins;

                if (allowedOrigins?.Any() ?? false)
                {
                    corsBuilder.WithOrigins(allowedOrigins.ToArray())
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                }
            });
    })
    .AddHttpClient()
    .Configure<Configuration>(builder.Configuration)
    .Configure<ConnectionStringsConfiguration>(builder.Configuration.GetSection("ConnectionStrings"))
    .Configure<WorkflowConfiguration>(builder.Configuration.GetSection("WorkflowService"))
    .Configure<TokenConfiguration>(builder.Configuration.GetSection("TokenService"))
    .AddLogging()
    .AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = OktaDefaults.ApiAuthenticationScheme;
        options.DefaultChallengeScheme = OktaDefaults.ApiAuthenticationScheme;
        options.DefaultSignInScheme = OktaDefaults.ApiAuthenticationScheme;
    })
    .AddOktaWebApi(new OktaWebApiOptions()
    {
        OktaDomain = "https://org.oktapreview.com",
        AuthorizationServerId = "aus17ct73zmZrZjbh0h8",
        Audience = "0oa173fmolqChJbj00h8"
    });

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage()
        .UseSwagger()
        .UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "NCL.StockSupplyChain.PurchaseOrder.Web.API"));

    // This line enables more detailed stacktrace for auth code errors, Idendity framework, auth middleware etc
    IdentityModelEventSource.ShowPII = true;
}

app.UseHttpsRedirection()
    .UseRouting()
    .UseAuthentication()
    .UseAuthorization()
    .UseCors(corsPolicyName)
    .UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

await app.RunAsync();

These two lines of code have to be in this order otherwise it will error:

.UseAuthentication()
.UseAuthorization()

Hopefully this helps someone who gets stuck with the error: System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://org.oktapreview.com/oauth2/aus17ct73zmZrZjbh0h8/.well-known/openid-configuration'. in the future because I thought I had configured Okta incorrectly.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 nick gowdy