Skip to content
This repository has been archived by the owner on Dec 13, 2018. It is now read-only.

[Authorize] http -> https default behaviour? #798

Closed
mikes-gh opened this issue Apr 25, 2016 · 15 comments
Closed

[Authorize] http -> https default behaviour? #798

mikes-gh opened this issue Apr 25, 2016 · 15 comments

Comments

@mikes-gh
Copy link
Contributor

Does [Authorise] always redirect to https?

What I am trying to do is pulish to IIS but debug on plain http kestrel server on dev machine.
Whats the best way of going about this.

I tried using conditional compilation on [RequireHttps] which works but it looks like [Authorize] always try for https.

Obviously in production I am using https. I didn't really want to add https support to kestrel for dev only due to certificate setup and just to keep it simple.

@Tratcher
Copy link
Member

What authentication middleware are you using? Cookies? OAuth? OIDC?

Is the redirect local or remote?

When generating local redirects we use the same scheme as the current request.

@mikes-gh
Copy link
Contributor Author

I am using Google and and Facebook so I guess OAuth and the following Indentity setup.

 services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();
            services.Configure<IdentityOptions>(options =>
            {
                options.Cookies.ApplicationCookie.LoginPath = new PathString("/default/Account/Login/");
            });

Probably misunderstanding the process sorry.

@Tratcher
Copy link
Member

That seems fine. Please share the rest of your Startup

@mikes-gh
Copy link
Contributor Author

@Tratcher

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Reports2.Models;
using Reports2.Services;
using Reports2.Authorization;
using System.Net.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Http;
using System.Diagnostics;
using System.Net;

namespace Reports2
{
    public class Startup
    {
        public IConfigurationRoot Configuration { get; set; }
        public Startup(IHostingEnvironment env)
        {
            // Set up configuration sources.
            var builder = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json")
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();            
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardLimit = 2;
                options.KnownProxies.Add(IPAddress.Parse("192.168.1.58"));
            }
            );
            // Add framework services.

            services
                .AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(Configuration["Data:default:ConnectionString"]))
              .AddDbContext<TradingCompanyDbContext>(options =>
                    options.UseSqlServer(Configuration["Data:default:ConnectionString"]));


            services.AddIdentity<ApplicationUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();
            services.Configure<IdentityOptions>(options =>
            {
                options.Cookies.ApplicationCookie.LoginPath = new PathString("/default/Account/Login/");
            });

            services.AddMvc();
            services.AddMvcDnx();
            services.AddAuthorization();
            services.AddScoped<IAuthorizationHandler, AccountNoAuthorizationHandler>();
            services.AddScoped<IAuthorizationHandler, AccountNosAuthorizationHandler>();
            //services.AddScoped<TradingCompanyDbContext>();

            // Add application services.
            services.AddTransient<IEmailSender, AuthMessageSender>();
            services.AddTransient<ISmsSender, AuthMessageSender>();
            services.AddTransient<IInvoiceService, InvoiceService>();
            services.AddTransient<IStatementService, StatementService>();
            services.AddTransient<IHomeService, HomeService>();
            services.AddTransient<IAccountPermissionsService, AccountPermissionService>();
            services.AddSingleton<IConfiguration>(Configuration);
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

        {

            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();
            loggerFactory.AddProvider(new TextLoggingProvider());

            if (env.IsDevelopment())
            {
                //app.UseBrowserLink();
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");

                // For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859
                try
                {
                    using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
                        .CreateScope())
                    {
                        serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
                             .Database.Migrate();
                    }
                }
                catch { }
            }

            app.UseHttpMethodOverride();

            app.UseStaticFiles();

            app.UseIdentity();

            app.UseFacebookAuthentication(new FacebookOptions
            {
#if DEBUG
                AppId = "xxxxxxxxxxxxxx",
                AppSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
#else
                AppId = "xxxxxxxxxxxxxxx",
                AppSecret = "xxxxxxxxxxxxxxxxxxxxxxx",
#endif
                Fields = {"first_name","last_name"},

                BackchannelHttpHandler = new HttpClientHandler()
                {
                    Proxy = new Reports2.Utilities.WebProxy("http://aesproxy.surcouf.local:3128")
                }
            });
            app.UseGoogleAuthentication(new GoogleOptions
            {
                ClientId = "xxxxxxxxxxxxxx",
                ClientSecret = "xxxxxxxxxxxxxxxxxxxxx",

                BackchannelHttpHandler = new HttpClientHandler()
                {
                    Proxy = new Reports2.Utilities.WebProxy("http://aesproxy.surcouf.local:3128")
                }
            });

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                     name: "tradingCompany",
                    template: "{tradingcompany:regex(^aes$|^mom$)}/{controller=Home}/{action=Index}/{id?}");
                routes.MapRoute(
                    name: "notradingCompany",
                    template: "{tradingcompany=default}/{controller=Home}/{action=Index}/{id?}");
            });
        }

    }
}

@Tratcher
Copy link
Member

Seems fine. One other place to check is your x-forwarded-* request headers. Please share the headers for an affected request.

@Tratcher
Copy link
Member

Nevermind, I was considering a different issue. Try putting this before MVC:

app.Run(context =>
{
  return context.Response.WriteAsync(context.Request.Scheme);
});

@mikes-gh
Copy link
Contributor Author

That gives a page whose only content is the text http 😄

I did some more testing. I was getting different results with chrome.
I deleted the browser history in IE and it worked.
Its as if IE had cached the redirect

Any idea what's going on here?

@Tratcher
Copy link
Member

Huh, that's a new one. Have you been able to repro it since clearing your cache?

@Eilon
Copy link
Member

Eilon commented Apr 28, 2016

In MVC there's a [RequireHttps] filter but that's about it. I'm not aware of anything else in the system that would do that.

@mikes-gh
Copy link
Contributor Author

I found this http://stackoverflow.com/questions/9130422/how-long-do-browsers-cache-http-301s
Require HTTPS attribute uses 301.
Its nor clear when (if ever) IE clears it's 301 cache.
This explains some other strange behaviour.I have been seeing.
Consider the developer removes the requirehttps attribute. If the dev tests using IE he will still see the HTTPS page. Depending on browser and what pages the dev has visited in testing ressults will be inconsistant. Confusing isn't it.

Is there a case for requirehttps using a 302?

@Eilon
Copy link
Member

Eilon commented Apr 28, 2016

When you have [RequireHttps] it's usually permanent, so 301 does make sense. It seems unlikely that someone would only temporarily want to have such a redirect.

@Eilon
Copy link
Member

Eilon commented Apr 28, 2016

(Except during development, I suppose.)

@mikes-gh
Copy link
Contributor Author

mikes-gh commented Apr 28, 2016

Yes but 301 means preeminent for ever. Perhaps you wanted to allow page in http having previously require https You can't undo that with 301. It's a one way trip. I'd be interested to see what other frameworks do I'll do some research.

@mikes-gh
Copy link
Contributor Author

Put it this way [RequireHttps] is an attribute you can add and remove. It's just code after all. It's effect however is permenant and one way. The behaviour of the site can become different to the code.

Basically if you use this attribute perhaps by mistake even once you can never go back to the http version.

301 is more about moving entire sites forever.

@mikes-gh
Copy link
Contributor Author

I'm moving this to MVC where it belongs now I understand the issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants