'How to exclude a specific path in ASP.NET Core 5 so that the request is processed by ASP.NET and not by the static files?

So I have a frontend/SPA in Angular and a backend/API in ASP.NET Core 5. After building the frontend, the build files were copied to the backend's wwwroot folder.

I implemented an authentication flow with OpenIDConnect in my backend. This is triggered by the frontend and leads to a backend endpoint. So you will be redirected to the Identity Provider and back to the callback endpoint that ASP.NET provides.

Now when I open the website, ASP.NET serves me the static Angular files and this redirects me to the Endpoint which starts the Login/Auth process. The process end up redirecting me to https://localhost:5001/callback.

The problem now is that ASP.NET is not serving the request through the pre-configured callback path. It will forward the request to the static files so Angular will process the request.

So my question is: Is it possible to exclude specific paths so that they are processed via ASP.NET instead of the static files?

So far I've tried intercepting the request and only forwarding what doesn't have /api or /callback in the path. As described in these blogs/questions:

ConfigureServices in my Startup.cs looks like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "backend", Version = "v1" });
    });


    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie(options =>
    {
        options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
        options.Cookie.SameSite = SameSiteMode.Strict;
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromHours(2);
        options.SlidingExpiration = true;
        options.Cookie.MaxAge = TimeSpan.FromHours(2);
    })
    .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => ConfigureOpenIdConnect(options));

    services.AddControllersWithViews();


    services.AddSpaStaticFiles(configuration =>
    {
        configuration.RootPath = "wwwroot";
    });


    services.AddCors(options =>
    {
        options.AddDefaultPolicy(builder =>
        {
            builder.AllowAnyOrigin();
            builder.AllowAnyHeader();
            builder.AllowAnyMethod();
        });
    });
}

My Configure looks like this:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("v1/swagger.json", "backend v1"));
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseCors();
    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthentication();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller}/{action}/{id?}");
    });


    app.UseDefaultFiles();
    app.UseStaticFiles();
    app.UseSpa(spa =>
    {
        spa.Options.SourcePath = "../../frontend/";

        if (env.IsDevelopment())
        {
            spa.UseAngularCliServer(npmScript: "dev:start");
        }
    });
}
private void ConfigureOpenIdConnect(OpenIdConnectOptions options)
{
    options.Authority = Configuration.GetValue<string>("Authority");
    options.ClientId = Configuration.GetValue<string>("ClientId");
    options.ClientSecret = Configuration.GetValue<string>("ClientSecret");

    // Set response type to code
    options.ResponseMode = OpenIdConnectResponseMode.FormPost;

    // Configure the scope
    options.Scope.Clear();
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("offline_access");

    options.CallbackPath = new PathString("/callback");

    // This saves the tokens in the session cookie
    options.SaveTokens = true;
    options.UseTokenLifetime = false;
}

Update 1:

folder structure of the ASP.NET project: ASP.NET project


folder structure of wwwroot:

these are the Angular build files. In the assets folder is the font and some images ASP.NET project



Sources

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

Source: Stack Overflow

Solution Source