Hey everyone,
I’ve looked at other forum posts about this issue but I’m still none the wiser on how to fix it. I’m using Okta for an Asp.net MVC app and Asp.net Web API (Both dotnet 6). I log in to the MVC app with Oauth2 and I’m able to get the token. This is all happening while running both the MVC app and the Web API locally. I use the addresses https://localhost:7012
(App) and https://localhost:7296
(Web API)
This token is then used in the bearer header for the API requests but I always get the same error, no matter what changes I make:
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[3]
Exception occurred while processing message.
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://nandos.oktapreview.com/oauth2/aus17ct73zmZrZjbh0h8/.well-known/openid-configuration'.
---> System.IO.IOException: IDX20804: Unable to retrieve document from: 'https://nandos.oktapreview.com/oauth2/aus17ct73zmZrZjbh0h8/.well-known/openid-configuration'.
---> System.NotSupportedException: Serialization and deserialization of 'System.IntPtr' instances are not supported. Path: $.TargetSite.MethodHandle.Value.
---> System.NotSupportedException: Serialization and deserialization of 'System.IntPtr' instances are not supported.
at System.Text.Json.Serialization.Converters.UnsupportedTypeConverter`1.Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
--- End of inner exception stack trace ---
I’m using a custom authorization server as I thought the problem was that the default authorization server was too limited. Here is my MVC App config in Program.cs
:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OktaDefaults.MvcAuthenticationScheme;
})
.AddCookie()
.AddOktaMvc(new OktaMvcOptions
{
OktaDomain = oktaConfiguration.Domain,
ClientId = oktaConfiguration.ClientId,
ClientSecret = oktaConfiguration.ClientSecret,
CallbackPath = oktaConfiguration.CallbackPath,
AuthorizationServerId = "aus17ct73zmZrZjbh0h8",
Scope = new List<string> { "openid" }
});
And here is my Web API config in Program.cs
:
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OktaDefaults.ApiAuthenticationScheme;
options.DefaultChallengeScheme = OktaDefaults.ApiAuthenticationScheme;
options.DefaultSignInScheme = OktaDefaults.ApiAuthenticationScheme;
})
.AddOktaWebApi(new OktaWebApiOptions
{
OktaDomain = "https://nandos.oktapreview.com",
BackchannelHttpClientHandler = new MyLoggingHandler(logger),
AuthorizationServerId = "aus17ct73zmZrZjbh0h8",
Audience = "0oa173fmolqChJbj00h8"
});
I’m not sure what to do. I have a feeling that I’m missing something in Program.cs
in the Web API…
Here is the full code for MVC APP config Program.cs
:
using Lamar;
using Lamar.Microsoft.DependencyInjection;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.OpenApi.Models;
using NCL.StockSupplyChain.Common.Configuration;
using NCL.StockSupplyChain.PurchaseOrder.Web.UI.Configuration;
using NUglify.JavaScript;
using Okta.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
OktaConfiguration oktaConfiguration = builder.Configuration.GetSection("Okta").Get<OktaConfiguration>();
// 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();
});
});
// Add services to the container.
builder.Services.AddControllersWithViews()
.AddJsonOptions(jsonOptions => jsonOptions.JsonSerializerOptions.PropertyNamingPolicy = null);
builder.Services
.AddWebOptimizer(pipeline =>
{
pipeline.AddJavaScriptBundle("/js/bundle.js", new CodeSettings { MinifyCode = false },
"js/bundle/jquery-1.11.1.js",
"js/bundle/jquery-ui-1.11.1.js",
"js/bundle/jquery.blockUI.js",
"js/bundle/jquery.highlight.js",
"js/bundle/jquery.tooltipster.min.js",
"js/bundle/knockout-3.1.0.js",
"js/bundle/Api.js",
"js/bundle/control-ypw-selector.js",
"js/bundle/currencyconverter.js",
"js/bundle/date-picker.js",
"js/bundle/findin.js",
"js/bundle/findinpage.js",
"js/bundle/jsfieldvalidator.js",
"js/bundle/jslifecycle.js",
"js/bundle/moment.min.js",
"js/bundle/popcalendar.js",
"js/bundle/prodcat.js",
"js/bundle/utility.js",
"js/bundle/accounting.js");
pipeline.AddCssBundle("/css/bundle.css",
"css/bundle/PurchaseOrder.css",
"css/bundle/jquery-ui.css",
"css/bundle/tooltipster.css");
pipeline.AddCssBundle("/css/print-bundle.css",
"css/printpage.css",
"css/bundle/jquery-ui.css");
if (!builder.Environment.IsDevelopment())
{
pipeline.MinifyCssFiles();
pipeline.MinifyJsFiles();
}
})
.AddRouting(options => options.LowercaseUrls = true)
.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "NCL.StockSupplyChain.PurchaseOrder.Web.UI", Version = "v1" });
})
.AddLocalization()
.Configure<GlobalConfiguration>(builder.Configuration)
.Configure<ConnectionStringsConfiguration>(builder.Configuration.GetSection("ConnectionStrings"))
.Configure<ApplicationSettingsConfiguration>(builder.Configuration.GetSection("ApplicationSettings"))
.Configure<PublicEnvironmentConfiguration>(builder.Configuration.GetSection("PublicEnvironment"))
.Configure<OktaConfiguration>(builder.Configuration.GetSection("Okta"));
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OktaDefaults.MvcAuthenticationScheme;
})
.AddCookie()
.AddOktaMvc(new OktaMvcOptions
{
OktaDomain = oktaConfiguration.Domain,
ClientId = oktaConfiguration.ClientId,
ClientSecret = oktaConfiguration.ClientSecret,
CallbackPath = oktaConfiguration.CallbackPath,
AuthorizationServerId = "aus17ct73zmZrZjbh0h8",
Scope = new List<string> { "openid" }
});
builder.Services.AddMvc(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.UseSwagger()
.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "NCL.StockSupplyChain.PurchaseOrder.Web.UI"));
}
else
{
app.UseExceptionHandler("/Home/Error");
// 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()
.UseWebOptimizer()
.UseStaticFiles()
.UseRouting()
.UseAuthentication()
.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}");
app.Run();
And Web API:
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://nandos.oktapreview.com",
BackchannelHttpClientHandler = new MyLoggingHandler(logger),
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"));
}
app.UseHttpsRedirection()
.UseRouting()
.UseAuthentication()
.UseAuthorization()
.UseCors(corsPolicyName)
.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
await app.RunAsync();