0

I'm stuck with deploying a SPA (ASP.NET Core + identity + ReactJS, all built from 'ASP.NET Core With React.js' template in VS) to production. It works fine in the development environment, but when deploying to prod (non-Azure), the API starts to return 401s.

I went through Authentication and authorization for SPAs article, it says the following:

To deploy the app to production, the following resources need to be provisioned:
...
A production certificate to use for signing tokens.

I have a link to the .pfx certificate on the hosting, but I'm a bit lost on how to implement it (and whether I actually need it?). Most samples I see assume running from the local/development machine (i.e. generate a self-signed certificate and load it from the file, etc).

Below is the code (skipping some irrelevant service configuration). I'm looking for a link to a resource that explains the changes needed to be done to deploy this to production (or a code sample).

Code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));

    services.AddDatabaseDeveloperPageExceptionFilter();

    services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddIdentityServer()
            .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

    services.AddAuthentication()
            .AddIdentityServerJwt();

    services.AddControllersWithViews();
    services.AddRazorPages();

    // In production, the React files will be served from this directory
    services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/build";
        });
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseMigrationsEndPoint();
    }
    else
    {
        app.UseExceptionHandler("/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();
    app.UseStaticFiles();
    app.UseSpaStaticFiles();

    app.UseRouting();

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

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

    app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseReactDevelopmentServer(npmScript: "start");
            }
        });
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Eugene
  • 1,073
  • 1
  • 7
  • 7

1 Answers1

0

You need to provide a signing-key to IdentityServer, so that the keys issued by it are signed by the same key each time, even across re-deployments.

The answers to this question will show you how to add it to IdentitySever.

See also this link that provides this piece of code to add the key:

services.AddIdentityServer()
  // .AddTemporarySigningCredential() // Can be used for testing until a real cert is available
  .AddSigningCredential(new X509Certificate2(Path.Combine(".", "certs", "IdentityServer4Auth.pfx")))
Tore Nestenius
  • 16,431
  • 5
  • 30
  • 40