简体   繁体   中英

Identity with ASP.Net Core 3.1 - on not authenticated, the app is not redirecting to Login in production like it does in dev

I have an ASP.Net Core (3.1) web app that takes advantage of Identity. It works as desired on my dev box, but does not redirect to login in production.

Let me explain. I have a home/landing page with links to actions all over it. If a user clicks on an action that requires Authentication (I am using the [Authorize] tag to specify that in my controller), then the app should redirect to the Login page to allow the user to login first and then redirect to the desired action that they click. This works like magic almost completely out of the box with Identity on my dev machine . When I push to production, this doesn't work like that. It just sits on the home page with the URL changed to the action URL of the action clicked, which is OK I guess - at least it still enforces the Authentication - but I want the redirection.

My production machine is a redhat linux server with apache and .netcore 3.1 setup on it.

Here is my Startup:

public class Startup
{
    //private readonly IConfiguration _configuration;

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDistributedMemoryCache();

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

        services.AddDbContext<AAPDbContext>(options => {
            options.UseSqlServer(Configuration.GetConnectionString("AAP"));
        });
        services.AddDbContext<AuthDbContext>(options => {
            options.UseSqlServer(Configuration.GetConnectionString("AAP"));
        });

        services.AddTransient<IEmailSender, EmailSender>();
        services.Configure<AuthMessageSenderOptions>(Configuration);            
    }

    // 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();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");                
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        

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

Here is my IdentityHostingStartup (added by Scaffolding and then tweaked):

public class IdentityHostingStartup : IHostingStartup
{
    public void Configure(IWebHostBuilder builder)
    {
        builder.ConfigureServices((context, services) => {
            services.AddDbContext<AuthDbContext>(options =>
                options.UseSqlServer(
                    context.Configuration.GetConnectionString("AAP")));

            services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddRoles<ApplicationRole>()
                .AddRoleManager<RoleManager<ApplicationRole>>()
                .AddEntityFrameworkStores<AuthDbContext>();                

            services.ConfigureApplicationCookie(options =>
            {
                options.LoginPath = $"/Identity/Account/Login";
                options.LogoutPath = $"/Identity/Account/Logout";
                options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
            });
        });
    }
}

I'm hoping this is a weird situation where some setting needs to be flipped on the linux box that is different b/c my dev box is a Win10 machine.

Here is my config file for Apache:

<VirtualHost *:*>
    RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
</VirtualHost>

<VirtualHost *:80>
    ServerName blah blah
    RewriteEngine on

    RewriteRule .* https://blahblahblah [R=302,QSA,L]
</VirtualHost>
<VirtualHost *:443>
    ServerName blah blah

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000/

    SSLEngine on
    SSLCertificateFile /etc/pki/tls/certs/localhost.crt
    SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
    SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
</VirtualHost>

Based on the behavior that you're describing it's likely that something on your server is handling the unauthorized request before it's getting to your web application

I figured this out. It was the config file on the server.

I had it set to:

<VirtualHost *:*>
    RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
</VirtualHost>

<VirtualHost *:80>
    ServerName <removed server name>
    RewriteEngine on

    RewriteRule .* https://<removed server name> [R=302,QSA,L]
</VirtualHost>
<VirtualHost *:443>
    ServerName <removed server name>

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000/

    SSLEngine on
    SSLCertificateFile /etc/pki/tls/certs/localhost.crt
    SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
    SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
</VirtualHost>

...and it should have been:

<VirtualHost *:*>
    RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>

<VirtualHost *:80>
    RewriteEngine On
    RewriteCond %{HTTPS} !=on
    RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
</VirtualHost>

<VirtualHost *:443>
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000/
    ErrorLog /var/log/httpd/<removedappname>-error.log
    CustomLog /var/log/httpd/<removedappname>-access.log common
    SSLEngine on
    SSLProtocol all -SSLv2
    SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
    SSLCertificateFile /etc/pki/tls/certs/localhost.crt
    SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
    SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
</VirtualHost>

..which I found here: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-3.1

Moral of the story: never trust a server guy when he's guessing just like you. Always follow the documentation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM