Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
308 views
in Technique[技术] by (71.8m points)

reactjs - Error with IdentityServer when deploying asp.net Core REACT app to AWS Beanstalk

I have an asp.net core app with a React front-end that uses IdentityServer. It was created using the scaffold templates in Visual Studio 2019. The app works great locally, but fails when I deploy to an AWS beanstalk. The line of code it fails on is in the Configure method of my Startup.cs. app.UseIdentityServer().

Somewhere within UseIdentityServer() there is a null reference exception that is not visible to me, and I cannot reproduce when testing locally on my development machine.

Here is my Configure() method in Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            //app.UseDatabaseErrorPage();
        }
        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"); // Starts CRA automatically
                spa.UseProxyToSpaDevelopmentServer("http://localhost:3000"); // Must manually start CRA (yarn start)
            }
        });
    }
}

There error I get when checking the AWS beanstalk logs looks like this:

Jan 1 00:36:57 ip-172-30-2-135 web: #033[41m#033[30mfail#033[39m#033[22m#033[49m: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1] Jan 1 00:36:57 ip-172-30-2-135 web: An unhandled exception has occurred while executing the request. Jan 1 00:36:57 ip-172-30-2-135 web: System.NullReferenceException: Object reference not set to an instance of an object. Jan 1 00:36:57 ip-172-30-2-135 web: at Microsoft.Extensions.DependencyInjection.IdentityServerBuilderConfigurationExtensions.<>c.b__10_2(IServiceProvider sp) Jan 1 00:36:57 ip-172-30-2-135 web: at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context) Jan 1 00:36:57 ip-172-30-2-135 web: at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)

Has anybody run into this before? This is something that is specific to deploying to an AWS beanstalk. If I remove the UseIdentityServer() call, the app publishes and runs fine in AWS Beanstalk. I am publishing to a Linux beanstalk if that makes a difference. There must be something that needs to be configured differently with IdentityServer when deployed to Linux, or maybe something specific with AWS Beanstalk.

When running locally on my development machine, it is on Windows 10 in case that helps.

Edit: Adding ConfigureServices() method

public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<BarristerContext>(options =>
            options.UseNpgsql(
                Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<BarristerContext>()
            .AddDefaultTokenProviders();

        services.Configure<IdentityOptions>();
        
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Latest)
            .AddRazorPagesOptions(options =>
            {
                options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
                options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
            });

        services.ConfigureApplicationCookie(options =>
        {
            // Cookie settings
            options.Cookie.HttpOnly = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

            options.LoginPath = $"/Identity/Account/Login";
            options.LogoutPath = $"/Identity/Account/Logout";
            options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
        });

        // using Microsoft.AspNetCore.Identity.UI.Services;
        services.AddSingleton<IEmailSender, EmailSender>();

        services.AddIdentityServer(options => 
        {
            options.UserInteraction = new UserInteractionOptions()
            {
                LogoutUrl = "/Identity/account/logout",
                LoginUrl = "/Identity/account/login",
                LoginReturnUrlParameter = "returnUrl"
            };
        }).AddApiAuthorization<ApplicationUser, BarristerContext>();

        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";
        });

        //services.AddDatabaseDeveloperPageExceptionFilter();
    }

I will also note, I am targeting .Net 5 on this deployment, which according to AWS, should work fine as long as I select "Build self contained deployment bundle" when I publish via the AWS Toolkit for Visual Studio.

https://aws.amazon.com/blogs/developer/aws-elastic-beanstalk-adds-net-core-on-linux-platform/


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The difference between my local host and the AWS Beanstalk that was causing the error on the Beanstalk, was the Nginx proxy. I had to account for this by adding the following middleware in my ConfigureServices() method of my Startup.cs.

services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders =
                ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
        });

This is due to:

When HTTPS requests are proxied over HTTP, the original scheme (HTTPS) is lost and must be forwarded in a header.

Because an app receives a request from the proxy and not its true source on the Internet or corporate network, the originating client IP address must also be forwarded in a header.

The following article gives more details: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-5.0


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...